"""Validate the layout and frontmatter of an active-claude-github skill (#140).

CI gate that runs on every PR touching skill prose, scaffold_project,
release_project, or README. Catches the class of bugs surfaced by the
1.4.x release cycle: prose claims a behavior, install/load doesn't
deliver, unit tests don't see it because they don't exercise the
install path.

This validator implements the lighter "parse frontmatter + verify
structure" path from #140's open implementation questions; the
headless-Claude-Code path is deferred to a follow-up.

Checks performed:

1. ``SKILL.md`` exists at the skill directory root.
2. SKILL.md has YAML frontmatter (delimited by ``---`` lines), with
   required keys ``name`` and ``description``, both non-empty.
3. Every required topic file exists in the same directory:
   bootstrap, classification, commit-rules, multi-repo, recording,
   release, tools.

Run as ``python -m active_claude_github_mcp.skill_validator``.
"""
from __future__ import annotations

import argparse
import sys
from pathlib import Path
from typing import Sequence


REQUIRED_TOPICS: tuple[str, ...] = (
    "bootstrap.md",
    "classification.md",
    "commit-rules.md",
    "multi-repo.md",
    "recording.md",
    "release.md",
    "tools.md",
)

REQUIRED_FRONTMATTER_KEYS: tuple[str, ...] = ("name", "description")

DEFAULT_SKILL_DIR = Path(".claude/skills/active-claude-github")


class ValidationError(Exception):
    """Raised when a skill-validator check fails."""


def parse_frontmatter(content: str) -> dict[str, str]:
    """Extract a SKILL.md's YAML frontmatter as a flat key/value dict.

    Frontmatter is the block between the opening ``---`` line at the
    very start of the file and the next ``---`` line. Lines inside
    are parsed as ``key: value`` pairs; blank lines and lines without
    a colon are skipped. Values are trimmed.

    Raises ``ValidationError`` if frontmatter is missing or unterminated.
    """
    if not content.startswith("---\n"):
        raise ValidationError(
            "missing YAML frontmatter (file must start with `---`)"
        )
    end = content.find("\n---\n", 4)
    if end == -1:
        raise ValidationError("frontmatter not terminated by `---`")
    block = content[4:end]
    keys: dict[str, str] = {}
    for line in block.split("\n"):
        if ":" not in line:
            continue
        k, _, v = line.partition(":")
        keys[k.strip()] = v.strip()
    return keys


def validate_skill(skill_dir: Path) -> None:
    """Validate a skill directory's layout and SKILL.md frontmatter.

    Raises ``ValidationError`` on the first failure. Caller maps the
    raised message to a CI-friendly diagnostic.
    """
    skill_md = skill_dir / "SKILL.md"
    if not skill_md.exists():
        raise ValidationError(f"SKILL.md not found at {skill_md}")

    content = skill_md.read_text(encoding="utf-8")
    keys = parse_frontmatter(content)

    for required in REQUIRED_FRONTMATTER_KEYS:
        if required not in keys:
            raise ValidationError(
                f"frontmatter missing required key: {required!r}"
            )
        if not keys[required]:
            raise ValidationError(
                f"frontmatter key {required!r} is empty"
            )

    for topic in REQUIRED_TOPICS:
        path = skill_dir / topic
        if not path.exists():
            raise ValidationError(f"required topic file missing: {topic}")


def main(argv: Sequence[str] | None = None) -> int:
    parser = argparse.ArgumentParser(
        prog="active_claude_github_mcp.skill_validator",
        description=(
            "Validate active-claude-github skill layout (#140). "
            "Exits 0 on success, 1 on validation failure."
        ),
    )
    parser.add_argument(
        "--skill-dir",
        type=Path,
        default=DEFAULT_SKILL_DIR,
        help="Path to the skill directory (default: %(default)s)",
    )
    args = parser.parse_args(argv)

    try:
        validate_skill(args.skill_dir)
    except ValidationError as exc:
        print(f"::error::{exc}", file=sys.stderr)
        return 1

    print(
        f"OK: {args.skill_dir} validates; "
        f"{len(REQUIRED_TOPICS)} topic files present, "
        f"frontmatter complete"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
