"""
Vidu 业务服务封装
==================

通过 PlatformGateway 统一调用 Vidu API。

职责：
- 业务参数校验与默认值处理
- 结果提取与格式化
"""

from __future__ import annotations

import logging
from typing import Any

from fastapi import Request

from app.ai.adapters.constants import Method
from app.ai.adapters.vidu_adapter import ViduAdapter
from app.core.exceptions import PlatformError, PlatformErrorType
from app.platform_gateway import PlatformGateway

logger = logging.getLogger(__name__)


# Vidu 预设音色
VIDU_PRESET_VOICES = [
    {
        "voice_id": "tianxin_xiaoling",
        "name": "甜心小玲",
        "language": "zh",
        "description": "甜美可爱，活泼俏皮",
        "recommended": True,
        "previewUrl": "https://media.liche.cn/meijiaka-zy/voice/tianxin_xiaoling.mp3",
    },
    {
        "voice_id": "danya_xuejie",
        "name": "淡雅学姐",
        "language": "zh",
        "description": "淡雅知性，温婉柔和",
        "recommended": False,
        "previewUrl": "https://media.liche.cn/meijiaka-zy/voice/danya_xuejie.mp3",
    },
    {
        "voice_id": "Chinese (Mandarin)_Warm_Girl",
        "name": "温暖少女",
        "language": "zh",
        "description": "温暖亲切，清新自然",
        "recommended": False,
        "previewUrl": "https://media.liche.cn/meijiaka-zy/voice/Warm_Girl.mp3",
    },
    {
        "voice_id": "Chinese (Mandarin)_Radio_Host",
        "name": "电台男主播",
        "language": "zh",
        "description": "专业播报，沉稳有力",
        "recommended": False,
        "previewUrl": "https://media.liche.cn/meijiaka-zy/voice/Radio_Host.mp3",
    },
    {
        "voice_id": "Chinese (Mandarin)_Straightforward_Boy",
        "name": "率真弟弟",
        "language": "zh",
        "description": "率真爽朗，青春阳光",
        "recommended": False,
        "previewUrl": "https://media.liche.cn/meijiaka-zy/voice/Straightforward_Boy.mp3",
    },
    {
        "voice_id": "Chinese (Mandarin)_Gentleman",
        "name": "温润男声",
        "language": "zh",
        "description": "温润如玉，低沉磁性",
        "recommended": False,
        "previewUrl": "https://media.liche.cn/meijiaka-zy/voice/Gentleman.mp3",
    },
]

DEFAULT_VOICE_ID = "tianxin_xiaoling"


# ==================== 预设音色（模块级函数，不依赖 Service 实例）====================


def get_preset_voices() -> list[dict]:
    """获取预设音色列表"""
    return VIDU_PRESET_VOICES


def get_voice_by_id(voice_id: str) -> dict | None:
    """根据 ID 获取音色信息"""
    for voice in VIDU_PRESET_VOICES:
        if voice["voice_id"] == voice_id:
            return voice
    return None


# ==================== Service 层 ====================


async def get_vidu_service(request: Request) -> ViduService:
    """FastAPI Depends：从 app.state 获取全局 ViduService 实例。"""
    return request.app.state.vidu_service


class ViduService:
    """Vidu 业务服务封装

    通过 PlatformGateway 统一调用，自身负责业务参数校验与结果提取。
    并发控制由调用方（Scheduler SlotManager 或 API 层 Semaphore）负责。
    """

    def __init__(self, gateway: PlatformGateway):
        self.gateway = gateway

    async def synthesize(
        self,
        text: str,
        voice_id: str | None = None,
        speed: float = 1.0,
        volume: int = 0,
        pitch: int = 0,
        **kwargs,
    ) -> str:
        """同步语音合成，返回音频 URL。"""
        if not text or not text.strip():
            raise PlatformError(
                "text 不能为空",
                platform="vidu",
                retryable=False,
                error_type=PlatformErrorType.BAD_REQUEST,
            )

        voice = voice_id or DEFAULT_VOICE_ID

        result = await self.gateway.call_sync(
            platform="vidu",
            method=Method.TTS,
            payload={
                "text": text,
                "voice_id": voice,
                "speed": speed,
                "volume": volume,
                "pitch": pitch,
                **kwargs,
            },
        )

        if not result.success:
            # 原始错误记录日志，前端只收到友好提示
            logger.error(f"[Vidu TTS] 合成失败: {result.error_message}")
            raise PlatformError(
                "语音合成失败，请稍后重试",
                platform="vidu",
                retryable=result.retryable,
                error_type=PlatformErrorType.BAD_REQUEST,
            )

        audio_url = result.data.get("audio_url") if result.data else None
        if not audio_url:
            logger.error("[Vidu TTS] 合成成功但未返回音频 URL")
            raise PlatformError(
                "语音合成结果异常，请稍后重试",
                platform="vidu",
                retryable=False,
                error_type=PlatformErrorType.BAD_REQUEST,
            )

        logger.info(f"[Vidu TTS] 合成成功: voice_id={voice}, url={audio_url[:60]}...")
        return audio_url

    # ==================== 声音复刻 ====================

    async def clone_voice(
        self,
        audio_url: str,
        voice_id: str,
        text: str | None = None,
        prompt_audio_url: str | None = None,
        prompt_text: str | None = None,
    ) -> dict[str, Any]:
        """声音复刻（同步接口）。

        Returns:
            复刻结果 dict，包含 voice_id、demo_audio 等
        """
        trial_text = text or "你好，欢迎使用vidu开放平台"

        result = await self.gateway.call_sync(
            platform="vidu",
            method=Method.CLONE_VOICE,
            payload={
                "audio_url": audio_url,
                "voice_id": voice_id,
                "text": trial_text,
                "prompt_audio_url": prompt_audio_url,
                "prompt_text": prompt_text,
            },
        )

        if not result.success:
            logger.error(f"[Vidu Clone] 复刻失败: {result.error_message}")
            raise PlatformError(
                f"声音复刻失败: {result.error_message or '请稍后重试'}",
                platform="vidu",
                retryable=result.retryable,
                error_type=PlatformErrorType.BAD_REQUEST,
            )

        logger.info(f"[Vidu Clone] 复刻成功: voice_id={result.data.get('voice_id')}")
        return result.data or {}

    async def query_clone_task(self, voice_id: str) -> dict[str, Any]:
        """Vidu 声音复刻是同步接口，无独立查询。
        此方法仅做兼容，返回已知的 voice_id 信息。
        """
        return {"voice_id": voice_id, "status": "succeeded"}

    # ==================== 视频生成 ====================

    async def lip_sync_create(
        self,
        video_url: str,
        audio_url: str | None = None,
        text: str | None = None,
        voice_id: str | None = None,
        speed: float = 1.0,
        volume: int = 0,
        ref_photo_url: str | None = None,
        callback_url: str | None = None,
        task_id: str | None = None,
    ) -> str:
        """创建视频生成任务（异步接口），返回 task_id。

        Args:
            task_id: Async Engine 的内部任务 ID，callback 场景必须传入，
                确保 PlatformGateway 的映射与 Registry 中的 task key 一致。
        """
        result = await self.gateway.submit_task(
            platform="vidu",
            task_type=Method.LIP_SYNC,
            payload={
                "video_url": video_url,
                "audio_url": audio_url,
                "text": text,
                "voice_id": voice_id,
                "speed": speed,
                "volume": volume,
                "ref_photo_url": ref_photo_url,
            },
            callback_url=callback_url,
            internal_task_id=task_id,
        )

        if not result:
            raise PlatformError(
                "视频生成任务创建失败，请稍后重试",
                platform="vidu",
                retryable=False,
                error_type=PlatformErrorType.BAD_REQUEST,
            )

        logger.info(f"[Vidu LipSync] 任务创建成功: task_id={result}")
        return result

    async def lip_sync_query(self, task_id: str) -> dict[str, Any]:
        """查询视频生成任务状态及生成物（task_id 为内部 ID）。"""
        status = await self.gateway.query_task_by_internal_id(task_id)

        result_data = status.result or {}
        return {
            "state": ViduAdapter.denormalize_state(status.state),
            "creations": [{"url": result_data.get("video_url")}] if result_data.get("video_url") else [],
            "message": status.error_message,
        }
