import os
import yaml
from pathlib import Path
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
from glob import glob
from .paths import get_path_manager
from .logger import log_event


class SkillInfo(BaseModel):
    """Skill information model"""

    name: str = Field(..., description="Skill name")
    description: str = Field(..., description="Skill description")
    location: str = Field(..., description="Path to SKILL.md file")


class SkillManager:
    """Manage skills from SKILL.md files"""

    def __init__(self):
        self.skills: Dict[str, SkillInfo] = {}

    def _parse_skill_file(self, file_path: str) -> Optional[SkillInfo]:
        """Parse a SKILL.md file and extract metadata"""
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                content = f.read()

            # Extract frontmatter (YAML between --- markers)
            if content.startswith("---"):
                parts = content.split("---", 2)
                if len(parts) >= 3:
                    frontmatter = parts[1].strip()
                    metadata = yaml.safe_load(frontmatter)

                    if isinstance(metadata, dict) and "name" in metadata:
                        return SkillInfo(
                            name=metadata["name"],
                            description=metadata.get("description", ""),
                            location=file_path,
                        )
        except Exception as e:
            log_event("skill_parse_error", file=file_path, error=str(e))

        return None

    def scan_skills(self, directories: List[str]) -> None:
        """Scan directories for SKILL.md files"""
        for directory in directories:
            if not os.path.exists(directory):
                continue

            # Search for SKILL.md files directly in subdirectories
            # Pattern: directory/**/SKILL.md
            pattern = os.path.join(directory, "**", "SKILL.md")
            skill_files = glob(pattern, recursive=True)

            for skill_file in skill_files:
                skill_info = self._parse_skill_file(skill_file)
                if skill_info:
                    # Warn on duplicate skill names
                    if skill_info.name in self.skills:
                        log_event(
                            "skill_duplicate_warning",
                            name=skill_info.name,
                            existing=self.skills[skill_info.name].location,
                            duplicate=skill_file,
                        )

                    self.skills[skill_info.name] = skill_info

    def get_skill(self, name: str) -> Optional[SkillInfo]:
        """Get a skill by name"""
        return self.skills.get(name)

    def get_all_skills(self) -> List[SkillInfo]:
        """Get all loaded skills"""
        return list(self.skills.values())

    def load_skill_content(self, skill_name: str) -> Optional[str]:
        """Load the full content of a skill"""
        skill = self.get_skill(skill_name)
        if not skill:
            return None

        try:
            with open(skill.location, "r", encoding="utf-8") as f:
                return f.read()
        except Exception as e:
            log_event("skill_load_error", skill=skill_name, error=str(e))
            return None


def get_skill_directories() -> List[str]:
    """
    Get list of directories to scan for skills.

    Returns directories:
    - .dundun/skills/（本地）
    - ~/.dundun/skills/（全局）
    - src/assets/skills/（内置）
    """
    path_manager = get_path_manager()
    skill_dirs = path_manager.get_all_skill_dirs()
    return [str(d) for d in skill_dirs]


# ==================== 全局单例 ====================

_skill_manager: Optional[SkillManager] = None


def get_skill_manager() -> SkillManager:
    """获取全局 SkillManager 单例（首次调用时自动扫描）"""
    global _skill_manager
    if _skill_manager is None:
        _skill_manager = SkillManager()
        _skill_manager.scan_skills(get_skill_directories())
    return _skill_manager
