"""Skill loader for CLI commands.

This module provides filesystem-based skill loading for CLI operations (list, create, info).
It implements skill discovery and metadata extraction from SKILL.md files.
"""

from __future__ import annotations

import re
from pathlib import Path
from typing import TypedDict, Optional

from ieum.config import get_package_path


class SkillMetadata(TypedDict):
    """Skill metadata from SKILL.md frontmatter."""

    name: str
    description: str
    path: str


class ExtendedSkillMetadata(SkillMetadata):
    """Extended skill metadata for CLI display, adds source tracking."""

    source: str


# Re-export for CLI commands
__all__ = ["SkillMetadata", "ExtendedSkillMetadata", "list_skills", "get_builtin_skills_dir"]


def get_builtin_skills_dir() -> Path:
    """Get the path to built-in skills bundled with the package.

    Returns:
        Path to the builtin skills directory.
    """
    return get_package_path("skills/builtin")


def _parse_yaml_frontmatter(content: str) -> dict:
    """Parse YAML frontmatter from SKILL.md content.

    Args:
        content: Full content of SKILL.md file.

    Returns:
        Dictionary with parsed frontmatter fields.
    """
    # Check for frontmatter delimiter
    if not content.startswith("---"):
        return {}

    # Find the closing delimiter
    lines = content.split("\n")
    end_idx = -1
    for i, line in enumerate(lines[1:], start=1):
        if line.strip() == "---":
            end_idx = i
            break

    if end_idx == -1:
        return {}

    # Parse YAML-like frontmatter (simple key: value parsing)
    frontmatter = {}
    for line in lines[1:end_idx]:
        line = line.strip()
        if not line or line.startswith("#"):
            continue

        # Handle key: value format
        match = re.match(r'^([a-z_-]+):\s*(.*)$', line, re.IGNORECASE)
        if match:
            key = match.group(1).lower()
            value = match.group(2).strip()
            # Remove quotes if present
            if value.startswith('"') and value.endswith('"'):
                value = value[1:-1]
            elif value.startswith("'") and value.endswith("'"):
                value = value[1:-1]
            frontmatter[key] = value

    return frontmatter


def _discover_skills(skills_dir: Path) -> list[SkillMetadata]:
    """Discover skills in a directory.

    Args:
        skills_dir: Directory containing skill subdirectories.

    Returns:
        List of skill metadata from discovered SKILL.md files.
    """
    skills = []

    if not skills_dir.exists():
        return skills

    for item in skills_dir.iterdir():
        if not item.is_dir():
            continue

        skill_md = item / "SKILL.md"
        if not skill_md.exists():
            continue

        try:
            content = skill_md.read_text(encoding="utf-8")
            frontmatter = _parse_yaml_frontmatter(content)

            # Extract required fields with defaults
            name = frontmatter.get("name", item.name)
            description = frontmatter.get("description", "No description available")

            skills.append({
                "name": name,
                "description": description,
                "path": str(skill_md),
            })
        except Exception:
            # Skip skills that can't be read
            continue

    return skills


def list_skills(
    *,
    user_skills_dir: Path | None = None,
    project_skills_dir: Path | None = None,
    include_builtin: bool = True,
) -> list[ExtendedSkillMetadata]:
    """List skills from builtin, user, and/or project directories.

    Priority order (later overrides earlier):
    1. Builtin skills (bundled with package)
    2. User skills (~/.ieum/{agent}/skills/)
    3. Project skills (.ieum/skills/)

    Args:
        user_skills_dir: Path to the user-level skills directory.
        project_skills_dir: Path to the project-level skills directory.
        include_builtin: Whether to include built-in skills (default: True).

    Returns:
        Merged list of skill metadata from all sources, with project skills
        taking highest precedence.
    """
    all_skills: dict[str, ExtendedSkillMetadata] = {}

    # Load builtin skills first (lowest priority)
    if include_builtin:
        builtin_dir = get_builtin_skills_dir()
        if builtin_dir.exists():
            builtin_skills = _discover_skills(builtin_dir)
            for skill in builtin_skills:
                extended_skill: ExtendedSkillMetadata = {**skill, "source": "builtin"}
                all_skills[skill["name"]] = extended_skill

    # Load user skills second (override builtin)
    if user_skills_dir and user_skills_dir.exists():
        user_skills = _discover_skills(user_skills_dir)
        for skill in user_skills:
            extended_skill: ExtendedSkillMetadata = {**skill, "source": "user"}
            all_skills[skill["name"]] = extended_skill

    # Load project skills last (highest priority)
    if project_skills_dir and project_skills_dir.exists():
        project_skills = _discover_skills(project_skills_dir)
        for skill in project_skills:
            extended_skill: ExtendedSkillMetadata = {**skill, "source": "project"}
            all_skills[skill["name"]] = extended_skill

    return list(all_skills.values())


def get_skill_content(skill_path: str | Path) -> str:
    """Get the full content of a skill file.

    Args:
        skill_path: Path to the SKILL.md file.

    Returns:
        Full content of the skill file.
    """
    return Path(skill_path).read_text(encoding="utf-8")


def extract_skill_instructions(content: str) -> str:
    """Extract skill instructions from SKILL.md (content after frontmatter).

    Args:
        content: Full content of SKILL.md file.

    Returns:
        Skill instructions without YAML frontmatter.
    """
    if not content.startswith("---"):
        return content

    # Find the closing delimiter
    lines = content.split("\n")
    end_idx = -1
    for i, line in enumerate(lines[1:], start=1):
        if line.strip() == "---":
            end_idx = i
            break

    if end_idx == -1:
        return content

    # Return content after frontmatter
    return "\n".join(lines[end_idx + 1:]).strip()
