#!/usr/bin/env python3
"""Validate an emitted RRC JSON artifact against source receipts.

This is an I/O-only shim: it performs no admissibility decisions. It checks:
  - JSON parses
  - required top-level fields are present
  - every row has required fields
  - equation_ids are unique
  - promotion is 'not_promoted' everywhere
  - alignment_score matches alignment_status mapping
"""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path
from typing import Any


SCORE_MAP = {
    "aligned_exact": 100,
    "aligned_proxy": 86,
    "compatible_structural_projection": 72,
    "alignment_warning": 35,
    "missing_prediction": 0,
}

REQUIRED_TOP = {"schema", "claim_boundary", "summary", "rows"}
REQUIRED_ROW = {
    "equation_id",
    "name",
    "shape",
    "status",
    "alignment_status",
    "alignment_score",
    "promotion",
    "warnings",
    "receipt_valid",
}


def validate(data: dict[str, Any]) -> list[str]:
    errors: list[str] = []
    missing_top = REQUIRED_TOP - data.keys()
    if missing_top:
        errors.append(f"missing top-level fields: {sorted(missing_top)}")
        return errors

    rows = data.get("rows", [])
    if not isinstance(rows, list):
        errors.append("'rows' must be a list")
        return errors

    ids = set()
    for idx, row in enumerate(rows):
        missing_row = REQUIRED_ROW - row.keys()
        if missing_row:
            errors.append(f"row {idx}: missing fields {sorted(missing_row)}")
            continue

        eq_id = row["equation_id"]
        if eq_id in ids:
            errors.append(f"duplicate equation_id: {eq_id}")
        ids.add(eq_id)

        if row["promotion"] != "not_promoted":
            errors.append(
                f"row {idx} ({eq_id}): promotion must be 'not_promoted', "
                f"got {row['promotion']!r}"
            )

        expected_score = SCORE_MAP.get(row["alignment_status"])
        if expected_score is None:
            errors.append(
                f"row {idx} ({eq_id}): unknown alignment_status "
                f"{row['alignment_status']!r}"
            )
        elif row["alignment_score"] != expected_score:
            errors.append(
                f"row {idx} ({eq_id}): alignment_score {row['alignment_score']} "
                f"does not match status {row['alignment_status']!r} ({expected_score})"
            )

    return errors


def main() -> int:
    parser = argparse.ArgumentParser(description="Validate RRC emitted JSON")
    parser.add_argument("json_file", help="path to emitted JSON file")
    args = parser.parse_args()

    path = Path(args.json_file)
    if not path.exists():
        print(f"ERROR: file not found: {path}", file=sys.stderr)
        return 1

    try:
        data = json.loads(path.read_text(encoding="utf-8"))
    except json.JSONDecodeError as e:
        print(f"ERROR: invalid JSON: {e}", file=sys.stderr)
        return 1

    errors = validate(data)
    if errors:
        print("VALIDATION FAILED", file=sys.stderr)
        for err in errors:
            print(f"  - {err}", file=sys.stderr)
        return 1

    rows = data.get("rows", [])
    print(f"OK: {len(rows)} rows, schema={data.get('schema')}")
    return 0


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