"""Skill 注册表

提供 Skill 的注册、查询和执行接口
"""

import logging
from typing import Any, Awaitable, Callable, Dict, List, Optional

from .base import BaseSkill, SkillCollection, SkillContext, SkillResult
from .loader import SkillLoader, get_skill_loader, reload_skill_loader

logger = logging.getLogger("agent")


class SkillRegistry:
    """Skill 注册表

    管理所有已加载的 Skill，提供查询和执行接口
    """

    def __init__(self, loader: Optional[SkillLoader] = None):
        self._loader = loader or get_skill_loader()
        self._skills: Dict[str, BaseSkill] = {}
        self._disabled: Dict[str, bool] = {}  # 记录被禁用的 Skill
        self._hooks: Dict[str, List[Callable[[str, Dict], Awaitable[Any]]]] = {
            "before_execute": [],
            "after_execute": [],
        }

    def load_skills(self, enabled_skills: Optional[List[str]] = None) -> SkillCollection:
        """加载所有 Skill

        Args:
            enabled_skills: 启用的 Skill 名称列表，None 表示全部加载
        """
        collection = self._loader.load_all(enabled_skills)
        self._skills.clear()

        for skill in collection.list_skills():
            self._skills[skill.name] = skill

        logger.debug(f"[SkillRegistry] 已加载 {len(self._skills)} 个 Skill")
        return collection

    def reload(self) -> SkillCollection:
        """重新加载所有 Skill"""
        self._skills.clear()
        self._disabled.clear()
        reload_skill_loader()
        return self.load_skills()

    def get_skill(self, name: str) -> Optional[BaseSkill]:
        """获取 Skill"""
        return self._skills.get(name)

    def add_skill(self, skill: BaseSkill):
        """添加 Skill"""
        self._skills[skill.name] = skill

    def remove_skill(self, name: str) -> bool:
        """移除 Skill"""
        if name in self._skills:
            del self._skills[name]
            return True
        return False

    def enable_skill(self, name: str) -> bool:
        """启用 Skill"""
        if name in self._disabled:
            self._disabled[name] = False
            return True
        return False

    def disable_skill(self, name: str) -> bool:
        """禁用 Skill"""
        if name in self._skills:
            self._disabled[name] = True
            return True
        return False

    def is_enabled(self, name: str) -> bool:
        """检查 Skill 是否启用"""
        return self._disabled.get(name, False) is False

    def list_skills(self, include_disabled: bool = False) -> List[BaseSkill]:
        """列出所有 Skill"""
        if include_disabled:
            return list(self._skills.values())
        return [s for s in self._skills.values() if self.is_enabled(s.name)]

    def list_by_category(self, category: str) -> List[BaseSkill]:
        """按分类列出 Skill"""
        return [s for s in self._skills.values() if s.category == category and self.is_enabled(s.name)]

    def list_names(self) -> List[str]:
        """列出所有 Skill 名称"""
        return [s.name for s in self._skills.values() if self.is_enabled(s.name)]

    @property
    def categories(self) -> List[str]:
        """获取所有分类"""
        return list(set(s.category for s in self._skills.values() if self.is_enabled(s.name)))

    async def execute(self, name: str, args: Dict[str, Any], context: SkillContext) -> SkillResult:
        """执行 Skill

        Args:
            name: Skill 名称
            args: Skill 参数
            context: 执行上下文

        Returns:
            SkillResult: 执行结果
        """
        # 检查 Skill 是否存在
        skill = self.get_skill(name)
        if not skill:
            return SkillResult(
                success=False,
                message=f"Skill '{name}' 不存在",
                error=f"Skill '{name}' not found"
            )

        # 检查 Skill 是否启用
        if not self.is_enabled(name):
            return SkillResult(
                success=False,
                message=f"Skill '{name}' 已禁用",
                error=f"Skill '{name}' is disabled"
            )

        # 执行 before_execute 钩子
        for hook in self._hooks["before_execute"]:
            try:
                await hook(name, args)
            except Exception as e:
                logger.warning(f"[SkillRegistry] before_execute 钩子执行失败: {e}")

        try:
            # 执行 Skill
            result = await skill.execute(args, context)

            # 执行 after_execute 钩子
            for hook in self._hooks["after_execute"]:
                try:
                    await hook(name, args, result)
                except Exception as e:
                    logger.warning(f"[SkillRegistry] after_execute 钩子执行失败: {e}")

            return result

        except Exception as e:
            logger.error(f"[SkillRegistry] Skill '{name}' 执行失败: {e}", exc_info=True)
            return SkillResult(
                success=False,
                message=f"Skill 执行失败: {str(e)}",
                error=str(e)
            )

    def register_hook(self, event: str, hook: Callable[[str, Dict], Awaitable[Any]]):
        """注册钩子

        Args:
            event: 事件名称 (before_execute, after_execute)
            hook: 钩子函数
        """
        if event in self._hooks:
            self._hooks[event].append(hook)

    def to_function_calls(self) -> List[Dict[str, Any]]:
        """转换为 Function Call 格式列表"""
        return [s.to_function_call() for s in self.list_skills()]

    def __len__(self) -> int:
        return len(self._skills)

    def __contains__(self, name: str) -> bool:
        return name in self._skills and self.is_enabled(name)


# ============================================================================
# 全局注册表实例
# ============================================================================


_registry: Optional[SkillRegistry] = None


def get_skill_registry() -> SkillRegistry:
    """获取全局 Skill 注册表"""
    global _registry
    if _registry is None:
        _registry = SkillRegistry()
        _registry.load_skills()
    return _registry


def reload_skill_registry() -> SkillRegistry:
    """重新加载 Skill 注册表"""
    global _registry
    _registry = SkillRegistry()
    _registry.load_skills()
    return _registry
