from pathlib import Path
from typing import Dict, List, Optional

from pygeai.skills.detector import AgentDetector
from pygeai.skills.installer import SkillInstaller
from pygeai.skills.models import Agent, Skill
from pygeai.skills.validator import SkillValidator


class SkillsEngine:
    """Main engine for skills management."""

    def __init__(self):
        self.validator = SkillValidator()
        self.detector = AgentDetector()
        self.installer = SkillInstaller()
        self.builtin_path = Path(__file__).parent / "builtin"

    def list_builtin_skills(self, category: Optional[str] = None) -> List[Skill]:
        """List built-in GEAI skills, optionally filtered by category."""
        skills = []
        if not self.builtin_path.exists():
            return skills

        for skill_dir in self.builtin_path.iterdir():
            if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists():
                skill = self.load_skill(skill_dir)
                if skill:
                    if category is None or skill.category == category:
                        skills.append(skill)
        return sorted(skills, key=lambda s: s.name)

    def list_categories(self) -> Dict[str, List[Skill]]:
        """Group skills by category."""
        categories = {}
        for skill in self.list_builtin_skills():
            cat = skill.category
            if cat not in categories:
                categories[cat] = []
            categories[cat].append(skill)
        return categories

    def load_skill(self, skill_path: Path) -> Optional[Skill]:
        """Load and validate a skill from directory."""
        skill_md = skill_path / "SKILL.md"
        if not skill_md.exists():
            return None

        try:
            content = skill_md.read_text()
            skill = self.validator.parse_skill_md(content, skill_path)
            return skill
        except Exception:
            return None

    def get_skill(self, skill_name: str) -> Optional[Skill]:
        """Get a specific built-in skill by name."""
        skill_path = self.builtin_path / skill_name
        if skill_path.exists():
            return self.load_skill(skill_path)
        return None

    def detect_agents(self) -> List[Agent]:
        """Detect installed coding agents."""
        return self.detector.detect_all()

    def get_supported_agents(self) -> List[str]:
        """Get list of supported agent names."""
        return self.detector.list_supported_agents()

    def install_skill(
        self,
        skill: Skill,
        agents: Optional[List[Agent]] = None,
        global_install: bool = False,
    ) -> Dict[str, bool]:
        """
        Install skill to coding agent(s).

        Returns dict mapping agent names to success status.
        """
        if agents is None:
            agents = self.detect_agents()

        results = {}
        for agent in agents:
            success = self.installer.install(skill, agent, global_install=global_install)
            results[agent.name] = success

        return results

    def uninstall_skill(
        self,
        skill_name: str,
        agents: Optional[List[Agent]] = None,
        global_install: bool = False,
    ) -> Dict[str, bool]:
        """
        Uninstall skill from coding agent(s).

        Returns dict mapping agent names to success status.
        """
        if agents is None:
            agents = self.detect_agents()

        results = {}
        for agent in agents:
            success = self.installer.uninstall(skill_name, agent, global_install=global_install)
            results[agent.name] = success

        return results

    def validate_skill(self, skill_path: Path) -> tuple[bool, List[str]]:
        """
        Validate skill structure and SKILL.md format.

        Returns (is_valid, error_messages).
        """
        return self.validator.validate(skill_path)
