"""Skill discovery and parsing — loads skill definitions from markdown files."""

from __future__ import annotations

from pathlib import Path

import yaml
from pydantic import BaseModel, Field

from loom.exceptions import SkillNotFoundError

BUILTIN_DIR = Path(__file__).parent / "builtin"


class SkillDefinition(BaseModel):
    name: str
    version: str = "1.0"
    description: str = ""
    inputs: list[str] = Field(default_factory=list)
    outputs: list[str] = Field(default_factory=list)
    model: str | None = None
    temperature: float | None = None
    max_tokens: int | None = None
    prompt_template: str = ""
    source_path: str | None = None


def parse_skill_file(path: Path) -> SkillDefinition:
    """Parse a skill markdown file with YAML frontmatter delimited by ---."""
    text = path.read_text()
    parts = text.split("---", 2)
    if len(parts) < 3:
        raise ValueError(f"Skill file {path} missing --- delimiters for YAML frontmatter")

    frontmatter = yaml.safe_load(parts[1]) or {}
    prompt_body = parts[2].strip()

    return SkillDefinition(
        name=frontmatter.get("name", path.stem),
        version=frontmatter.get("version", "1.0"),
        description=frontmatter.get("description", ""),
        inputs=frontmatter.get("inputs", []),
        outputs=frontmatter.get("outputs", []),
        model=frontmatter.get("model"),
        temperature=frontmatter.get("temperature"),
        max_tokens=frontmatter.get("max_tokens"),
        prompt_template=prompt_body,
        source_path=str(path),
    )


def discover_skills(project_dir: str | Path | None = None) -> dict[str, SkillDefinition]:
    """Load skills from built-in, global, and project directories. Last wins."""
    skills: dict[str, SkillDefinition] = {}

    # 1. Built-in skills
    if BUILTIN_DIR.is_dir():
        for f in sorted(BUILTIN_DIR.glob("*.md")):
            skill = parse_skill_file(f)
            skills[skill.name] = skill

    # 2. Global user skills
    global_dir = Path.home() / ".loom" / "skills"
    if global_dir.is_dir():
        for f in sorted(global_dir.glob("*.md")):
            skill = parse_skill_file(f)
            skills[skill.name] = skill

    # 3. Project-local skills
    if project_dir:
        project_skills = Path(project_dir) / ".loom" / "skills"
        if project_skills.is_dir():
            for f in sorted(project_skills.glob("*.md")):
                skill = parse_skill_file(f)
                skills[skill.name] = skill

    return skills


def load_skill(name: str, project_dir: str | Path | None = None) -> SkillDefinition:
    """Load a single skill by name. Raises SkillNotFoundError if missing."""
    skills = discover_skills(project_dir)
    if name not in skills:
        raise SkillNotFoundError(name)
    return skills[name]
