#!/usr/bin/env python3
"""Validate CARBON's independently pageable item library."""

from __future__ import annotations

import json
import re
import sys
from pathlib import Path

SKILL_ROOT = Path(__file__).resolve().parents[1]
ITEMS_ROOT = SKILL_ROOT / "references" / "items"
TEST_ID = re.compile(r"^- \*\*([A-Z][A-Z0-9-]*-\d{3})\*\*", re.MULTILINE)
LINK = re.compile(r"\[[^\]]+\]\(([^)#]+)(?:#[^)]+)?\)")
REQUIRED_PHRASES = {
    "explicit emoticon coverage": "emoticon",
    "explicit emoji coverage": "emoji",
    "retry or recovery coverage": ("retry", "recover"),
}


def main() -> int:
    errors: list[str] = []
    all_ids: dict[str, Path] = {}
    test_total = 0
    item_files = [
        path for path in sorted(ITEMS_ROOT.glob("*/*.md")) if path.name != "index.md"
    ]
    index_files = sorted(ITEMS_ROOT.glob("**/index.md"))

    for path in item_files:
        source = path.read_text(encoding="utf-8")
        ids = TEST_ID.findall(source)
        relative = path.relative_to(SKILL_ROOT)
        test_total += len(ids)

        if len(ids) < 24:
            errors.append(f"{relative}: only {len(ids)} test cases; minimum is 24")
        if source.count("\n# ") + source.startswith("# ") != 1:
            errors.append(f"{relative}: expected exactly one H1")
        if "## Comprehensive per-item coverage" not in source:
            errors.append(f"{relative}: missing comprehensive coverage section")

        lowered = source.lower()
        for label, needles in REQUIRED_PHRASES.items():
            if isinstance(needles, str):
                needles = (needles,)
            if not any(needle in lowered for needle in needles):
                errors.append(f"{relative}: missing {label}")

        for test_id in ids:
            if test_id in all_ids:
                errors.append(
                    f"duplicate {test_id}: {all_ids[test_id].relative_to(SKILL_ROOT)} "
                    f"and {relative}"
                )
            all_ids[test_id] = path

        for target in LINK.findall(source):
            resolved = (path.parent / target).resolve()
            if not resolved.exists():
                errors.append(f"{relative}: missing link target {target}")

    for path in index_files:
        source = path.read_text(encoding="utf-8")
        relative = path.relative_to(SKILL_ROOT)
        if TEST_ID.search(source):
            errors.append(f"{relative}: index must not contain test cases")
        for target in LINK.findall(source):
            resolved = (path.parent / target).resolve()
            if not resolved.exists():
                errors.append(f"{relative}: missing link target {target}")

    result = {
        "item_files": len(item_files),
        "index_files": len(index_files),
        "test_cases": test_total,
        "unique_test_ids": len(all_ids),
        "minimum_tests_per_item": min(
            (
                len(TEST_ID.findall(path.read_text(encoding="utf-8")))
                for path in item_files
            ),
            default=0,
        ),
        "errors": errors,
    }
    print(json.dumps(result, indent=2))
    return 1 if errors else 0


if __name__ == "__main__":
    sys.exit(main())
