"""
Skill 解析器 - 根据配置动态选择和合并 Skills

三级配置优先级：
1. 任务级动态配置（运行时指定）
2. 单集级配置（episodeSkillOverrides）
3. 项目级默认配置（defaultTaskSkills）
"""
from typing import List, Dict, Any, Optional
from app.models.project import SeriesProject, TaskType, SkillAssignment, TaskSkillConfig
from app.models.skill import Skill
from app.core.skills.skill_manager import get_skill_manager
from app.utils.logger import get_logger

logger = get_logger(__name__)


class SkillResolver:
    """Skill 解析器 - 负责根据三级配置动态选择 Skills"""

    def __init__(self):
        self.skill_manager = get_skill_manager()

    async def resolve_skills_for_task(
        self,
        project: SeriesProject,
        task_type: TaskType,
        episode_number: int,
        runtime_overrides: Optional[List[str]] = None
    ) -> List[Dict[str, Any]]:
        """
        解析指定任务的 Skill 配置

        Args:
            project: 项目
            task_type: 任务类型
            episode_number: 集数
            runtime_overrides: 运行时指定的 Skill ID 列表（最高优先级）

        Returns:
            解析后的 Skill 列表，包含 skill、parameters、references
        """
        # 1. 检查运行时覆盖（最高优先级）
        if runtime_overrides:
            logger.info(f"使用运行时覆盖 Skills: {runtime_overrides}")
            skills = []
            for skill_id in runtime_overrides:
                skill = await self.skill_manager.load_skill(skill_id)
                if skill:
                    skills.append({
                        "skill": skill,
                        "parameters": skill.config.parameters,
                        "references": await self.skill_manager.load_skill_references(skill_id)
                    })
            return skills

        # 2. 检查单集覆盖
        episode_override = project.episodeSkillOverrides.get(episode_number)
        if episode_override and not episode_override.use_project_default:
            logger.info(f"EP{episode_number} 使用单集覆盖配置")
            task_config = next(
                (c for c in episode_override.task_configs if c.task_type == task_type),
                None
            )
            if task_config:
                return await self._load_skills_from_config(task_config.skills)

        # 3. 使用项目默认配置
        task_config = next(
            (c for c in project.defaultTaskSkills if c.task_type == task_type),
            None
        )
        if task_config:
            logger.info(f"使用项目默认配置: task_type={task_type.value}, skills={[s.skill_id for s in task_config.skills]}")
            return await self._load_skills_from_config(task_config.skills)

        # 4. 回退到硬编码的默认值（兼容性）
        logger.warning(f"未找到 {task_type.value} 的配置，使用回退默认值")
        return await self._get_fallback_skills(task_type)

    async def _load_skills_from_config(
        self,
        assignments: List[SkillAssignment]
    ) -> List[Dict[str, Any]]:
        """从配置加载 Skills"""
        results = []

        # 按优先级排序
        sorted_assignments = sorted(assignments, key=lambda x: x.priority, reverse=True)

        for assignment in sorted_assignments:
            if not assignment.enabled:
                continue

            skill = await self.skill_manager.load_skill(assignment.skill_id)
            if not skill:
                logger.warning(f"Skill 未找到: {assignment.skill_id}")
                continue

            # 合并参数
            parameters = skill.config.parameters.copy()
            if assignment.parameter_overrides:
                parameters.update(assignment.parameter_overrides)

            # 加载参考文件
            references = await self.skill_manager.load_skill_references(skill.id)

            results.append({
                "skill": skill,
                "parameters": parameters,
                "references": references
            })

        return results

    async def _get_fallback_skills(self, task_type: TaskType) -> List[Dict[str, Any]]:
        """获取回退的默认 Skills（兼容现有硬编码）"""
        fallback_map = {
            TaskType.DIALOGUE: ["dialogue_writer_ancient", "dialogue-writer"],
            TaskType.OUTLINE: ["dialogue_writer_ancient"],
            TaskType.REVIEW: ["consistency_checker"],
            TaskType.CONSISTENCY: ["consistency_checker"],
        }

        skill_ids = fallback_map.get(task_type, [])

        for skill_id in skill_ids:
            skill = await self.skill_manager.load_skill(skill_id)
            if skill:
                references = await self.skill_manager.load_skill_references(skill_id)
                logger.info(f"使用回退 Skill: {skill_id}")
                return [{
                    "skill": skill,
                    "parameters": skill.config.parameters,
                    "references": references
                }]

        logger.error(f"未找到任何可用的 Skill for task_type={task_type.value}")
        return []


# 全局单例
_skill_resolver: Optional[SkillResolver] = None


def get_skill_resolver() -> SkillResolver:
    """获取 Skill 解析器单例"""
    global _skill_resolver
    if _skill_resolver is None:
        _skill_resolver = SkillResolver()
    return _skill_resolver
