"""Skill system - reusable prompt + script packages.

Skills are directories containing:
  SKILL.md  - description and instructions (appended to system prompt when active)
              Supports YAML frontmatter for metadata (Anthropic standard):
              ---
              name: skill-name           # required, must match directory name
              description: What it does  # required, helps model know when to use
              license: MIT               # optional
              compatibility: krim        # optional
              metadata:                  # optional, key-value pairs
                key: value
              ---
  *.sh      - optional helper scripts the model can reference

Search paths: ~/.krim/skills/ and .krim/skills/ (project overrides global)

Reference: https://github.com/anthropics/skills
"""

from __future__ import annotations

import re
from dataclasses import dataclass, field
from pathlib import Path


@dataclass
class Skill:
    name: str
    prompt: str   # contents of SKILL.md (without frontmatter)
    path: str     # directory path
    description: str = ""
    license: str = ""
    compatibility: str = ""
    metadata: dict[str, str] = field(default_factory=dict)


def _parse_skill_md(content: str, default_name: str) -> dict:
    """Parse SKILL.md with optional YAML frontmatter (Anthropic standard).

    Returns dict with: name, description, prompt, license, compatibility, metadata
    """
    result = {
        "name": default_name,
        "description": "",
        "prompt": content,
        "license": "",
        "compatibility": "",
        "metadata": {},
    }

    # Check for YAML frontmatter (--- at start and end)
    frontmatter_match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
    if frontmatter_match:
        frontmatter = frontmatter_match.group(1)
        result["prompt"] = content[frontmatter_match.end():]

        # Simple YAML parsing (avoid dependency on pyyaml)
        in_metadata = False
        for line in frontmatter.split('\n'):
            stripped = line.strip()

            # Check for metadata block
            if stripped.startswith('metadata:'):
                in_metadata = True
                continue

            # Parse metadata key-value pairs (indented)
            if in_metadata and line.startswith('  ') and ':' in stripped:
                key, val = stripped.split(':', 1)
                result["metadata"][key.strip()] = val.strip().strip('"\'')
                continue
            elif in_metadata and not line.startswith('  '):
                in_metadata = False

            # Parse top-level fields
            if stripped.startswith('name:'):
                result["name"] = stripped.split(':', 1)[1].strip().strip('"\'')
            elif stripped.startswith('description:'):
                result["description"] = stripped.split(':', 1)[1].strip().strip('"\'')
            elif stripped.startswith('license:'):
                result["license"] = stripped.split(':', 1)[1].strip().strip('"\'')
            elif stripped.startswith('compatibility:'):
                result["compatibility"] = stripped.split(':', 1)[1].strip().strip('"\'')

    return result


def discover_skills(
    global_dir: Path | None = None,
    project_dir: Path | None = None,
) -> dict[str, Skill]:
    """Find all available skills. Project skills override global ones."""
    skills = {}
    search_dirs = []

    if global_dir:
        search_dirs.append(global_dir / "skills")
    else:
        search_dirs.append(Path.home() / ".krim" / "skills")

    if project_dir:
        search_dirs.append(project_dir / "skills")

    for base in search_dirs:
        if not base.is_dir():
            continue
        for entry in sorted(base.iterdir()):
            if not entry.is_dir():
                continue
            skill_md = entry / "SKILL.md"
            if skill_md.is_file():
                content = skill_md.read_text()
                parsed = _parse_skill_md(content, entry.name)
                skills[entry.name] = Skill(
                    name=parsed["name"],
                    prompt=parsed["prompt"],
                    path=str(entry),
                    description=parsed["description"],
                    license=parsed["license"],
                    compatibility=parsed["compatibility"],
                    metadata=parsed["metadata"],
                )
    return skills


def inject_skill(system_prompt: str, skill: Skill) -> str:
    """Append skill instructions to the system prompt.

    DEPRECATED: Use inject_skill_metadata for progressive disclosure.
    """
    header = f"# Skill: {skill.name}"
    if skill.description:
        header += f"\n{skill.description}"
    return system_prompt + f"\n\n{header}\n\n{skill.prompt}"


def inject_skill_metadata(system_prompt: str, skills: dict[str, Skill]) -> str:
    """Inject only skill metadata (name, description) into system prompt.

    Progressive disclosure: full instructions load only when skill is invoked.
    This keeps initial context small (~100 tokens per skill).
    """
    if not skills:
        return system_prompt

    lines = ["# Available Skills",
             "Use the `skill` tool to invoke a skill when relevant to the task.",
             ""]
    for name, skill in skills.items():
        desc = skill.description or "(no description)"
        lines.append(f"- **{name}**: {desc}")

    return system_prompt + "\n\n" + "\n".join(lines)


def get_skill_content(skill: Skill) -> str:
    """Get full skill content for invocation.

    Called when agent invokes a skill via the skill tool.
    Returns the complete SKILL.md body.
    """
    return skill.prompt
