"""
脚本生成服务
============
"""

import asyncio
import logging
import time
from pathlib import Path

from app.ai.model_router import get_model_router
from app.ai.prompts import load_prompt_file, load_script_user_prompt
from app.schemas.script import ScriptShot
from app.services.ai_response_utils import (
    safe_parse_ai_json_response,
    validate_and_normalize_shots,
)

logger = logging.getLogger(__name__)


class ScriptService:
    """脚本生成服务"""


    def __init__(self):
        self.prompts_dir = Path(__file__).parent.parent / "ai" / "prompts"



    def _load_prompt(self, name: str) -> str:
        """加载 Prompt 模板"""
        prompt_file = self.prompts_dir / f"{name}.txt"
        if prompt_file.exists():
            return prompt_file.read_text(encoding="utf-8")
        return ""

    async def generate_script(
        self,
        category: str,
        filename: str,
        model: str | None = None,
    ) -> list[ScriptShot]:
        """
        同步生成脚本

        Args:
            category: 大类代码，如 "bk"
            filename: 提示词文件名，如 "水电改造避坑——水电改造的4个坑.txt"
            model: 指定模型

        Returns:
            分镜列表
        """
        # 获取 model_router
        model_router = await get_model_router()

        # 加载 Prompt
        system_prompt = load_prompt_file(category, filename)
        if not system_prompt:
            raise ValueError(f"未找到提示词: category={category}, filename={filename}")

        # 用户提示词
        user_prompt = load_script_user_prompt(
            topic=f"{category}/{filename}",
        )

        # 调用 AI 生成
        # 注意：system prompt 中已要求"只输出纯 JSON"，不依赖 response_format 参数
        result = await model_router.generate(
            prompt=user_prompt,
            system_prompt=system_prompt,
            model_id=model,
            task_type="script",
        )

        if not result.content or not result.content.strip():
            raise ValueError("AI 返回内容为空，请检查模型配置或重试")

        success, parsed_data, error_msg = safe_parse_ai_json_response(result.content)

        if not success:
            raise ValueError(error_msg or "AI 返回格式错误，无法解析为 JSON")

        try:
            shots_data = validate_and_normalize_shots(parsed_data)

            if not shots_data:
                raise ValueError("AI 返回的分镜数据为空或格式不正确")

            shots = [ScriptShot(**shot) for shot in shots_data]
            return shots

        except Exception as e:
            raise ValueError(f"分镜数据处理失败: {str(e)}")

    async def polish_content(
        self,
        content: str,
        polish_type: str = "voiceover",
        shot_type: str = "segment",
    ) -> str:
        """
        润色内容

        Args:
            content: 待润色内容
            polish_type: 润色类型，可选 "scene"（画面描述）或 "voiceover"（配音文本）
            shot_type: 镜头类型，可选 "segment"（分镜）或 "empty_shot"（空镜），仅用于画面润色

        Returns:
            润色后的内容
        """
        # 获取 model_router
        model_router = await get_model_router()

        # 从文件加载提示词模板
        if polish_type == "scene":
            # 画面润色需要根据镜头类型选择不同提示词
            if shot_type == "empty_shot":
                prompt_template = self._load_prompt("polish/scene_empty_shot")
            else:
                prompt_template = self._load_prompt("polish/scene_segment")

            # 如果特定类型的提示词不存在，回退到通用 scene 提示词
            if not prompt_template:
                prompt_template = self._load_prompt("polish/scene")
        else:
            # 配音文本润色
            prompt_template = self._load_prompt("polish/voiceover")

        if not prompt_template:
            # 最终回退
            prompt_template = "请润色以下内容：\n\n{content}"

        prompt = prompt_template.format(content=content)

        try:
            async with asyncio.timeout(15):
                result = await model_router.generate(
                    prompt=prompt,
                    task_type="polish",
                    max_tokens=300,
                )
                return result.content.strip()
        except TimeoutError:
            raise ValueError("润色请求超时，请重试")
        except Exception as e:
            raise ValueError(f"润色失败: {str(e)}")

    async def check_model_health(self) -> dict:
        """检查模型健康状态"""
        model_router = await get_model_router()
        health_results = await model_router.health_check()

        models = []
        available_count = 0
        recommended = None

        for _provider_id, health in health_results.items():
            model_info = {
                "id": health.id,
                "name": health.name,
                "is_available": health.is_available,
                "response_time": health.response_time,
                "last_error": health.last_error,
            }
            models.append(model_info)

            if health.is_available:
                available_count += 1
                if recommended is None or health.response_time < recommended.get(
                    "response_time", float("inf")
                ):
                    recommended = model_info

        total = len(models)

        return {
            "status": "healthy" if available_count > 0 else "unhealthy",
            "models": models,
            "recommended_model": recommended,
            "total_models": total,
            "available_models": available_count,
        }

    async def test_model(self, model_id: str | None = None) -> dict:
        """测试指定模型连接"""
        model_router = await get_model_router()


        start_time = time.time()

        try:
            result = await model_router.generate(
                prompt="你好",
                model_id=model_id,
                max_tokens=5,
            )

            response_time = (time.time() - start_time) * 1000

            return {
                "success": True,
                "model": result.model,
                "response_time": round(response_time, 2),
                "checked_at": time.strftime("%Y-%m-%dT%H:%M:%S"),
            }

        except Exception as e:
            return {
                "success": False,
                "model": model_id or "default",
                "error": str(e),
                "checked_at": time.strftime("%Y-%m-%dT%H:%M:%S"),
            }


# 全局单例
_script_service: ScriptService | None = None


def get_script_service() -> ScriptService:
    """获取 ScriptService 单例"""
    global _script_service
    if _script_service is None:
        _script_service = ScriptService()
    return _script_service
