#!/usr/bin/env python3
"""Validate a single scorecard.yaml against the evaluator schema.

Usage: python3 validate_scorecard.py <path-to-scorecard.yaml>
Exit:  0 on valid; 1 on first failure with a specific error on stderr.

Run after emitting a scorecard. Catches malformed scorecards before a reader
(or a downstream caller) trips over a missing field with no attribution.

Schema: 8 sub-criterion blocks (4 Code + 4 Product). Totals: total / available
/ normalized. Every sub-criterion carries score + evidence + data.
"""
import sys
from pathlib import Path

try:
    import yaml
except ImportError:
    print("[validate] FAIL: PyYAML not installed (pip install pyyaml)", file=sys.stderr)
    sys.exit(1)

REQUIRED_TOP = {
    "project", "commit_sha_pinned", "rubric_version", "scored_at",
    "agent_model",
    "gates_triggered", "short_circuited",
    "scored_sub_criteria", "total_sub_criteria",
    "total", "available", "normalized",
}

# 1.x Production-Grade Code — 12.5 pts each
CODE_SUBS = {
    "code_quality",
    "testing",
    "deployment_readiness",
    "maintainability",
}

# 2.x Product Thinking — 12.5 pts each
PRODUCT_SUBS = {
    "problem_substantiveness",   # 2.1
    "ux_mechanics",              # 2.2
    "value_articulation",        # 2.3
    "mechanical_ambition",       # 2.4
}

SUB_CRITERIA = CODE_SUBS | PRODUCT_SUBS


def fail(msg: str) -> None:
    print(f"[validate] FAIL: {msg}", file=sys.stderr)
    sys.exit(1)


def main(path: str) -> None:
    p = Path(path)
    if not p.exists():
        fail(f"file not found: {path}")

    try:
        doc = yaml.safe_load(p.read_text())
    except yaml.YAMLError as e:
        fail(f"YAML parse error in {path}: {e}")

    if not isinstance(doc, dict):
        fail(f"top-level of {path} is not a mapping")

    missing_top = REQUIRED_TOP - doc.keys()
    if missing_top:
        fail(f"missing top-level keys: {sorted(missing_top)}")

    missing_sub = SUB_CRITERIA - doc.keys()
    if missing_sub:
        fail(f"missing sub-criterion blocks: {sorted(missing_sub)}")

    for sub in SUB_CRITERIA:
        block = doc[sub]
        if not isinstance(block, dict):
            fail(f"{sub}: not a mapping")
        if "score" not in block:
            fail(f"{sub}: missing `score`")
        if "evidence" not in block:
            fail(f"{sub}: missing `evidence`")
        if "data" not in block:
            fail(f"{sub}: missing `data` block")

    # total_sub_criteria must be 8 under this schema.
    if doc.get("total_sub_criteria") != 8:
        fail(f"total_sub_criteria must be 8 (got {doc.get('total_sub_criteria')!r})")

    print(f"[validate] OK: {path}")
    sys.exit(0)


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python3 validate_scorecard.py <path-to-scorecard.yaml>", file=sys.stderr)
        sys.exit(2)
    main(sys.argv[1])
