#!/usr/bin/env python3
"""Recheck local A2 CAD evidence and write a bounded validation receipt."""
from pathlib import Path
import hashlib
import json
import re
import subprocess

root = Path(__file__).resolve().parent
parent = root.parent
board = root / "lamp_buck_lmr51450_a2_costdown.kicad_pcb"
schematic = root / "lamp_buck_lmr51450_a2_costdown.kicad_sch"
netlist = root / "lamp_buck_lmr51450_a2_costdown.net.xml"
drc = root / "A2-DRC.rpt"
erc = root / "A2-ERC.rpt"
parity_path = root / "pcb-net-parity.json"

def sha(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()

drc_text = drc.read_text(encoding="utf-8")
erc_text = erc.read_text(encoding="utf-8")
parity = json.loads(parity_path.read_text(encoding="utf-8"))
board_sha = sha(board)
checks = {
    "drc_zero_violations": bool(re.search(r"Found 0 DRC violations", drc_text)),
    "drc_zero_unconnected": bool(re.search(r"Found 0 unconnected (?:items|pads)", drc_text)),
    "erc_zero_errors_warnings": bool(re.search(r"ERC messages: 0  Errors 0  Warnings 0", erc_text)),
    "pad_net_parity_pass": parity.get("status") == "PASS" and not parity.get("pad_net_mismatches") and not parity.get("extra_board_pads"),
    "parity_receipt_current_board": parity.get("board_sha256") == board_sha,
    "expected_legacy_dnp_omissions_only": parity.get("component_ref_check", {}).get("expected_dnp_omissions") == ["C10", "C9", "D1", "R5"],
}
bom = (root / "bom-active-only.csv").read_text(encoding="utf-8")
checks["active_bom_contains_c5_c6_mpns"] = all(
    ref in bom and "TDK C4532X7R1C336M250KC" in bom for ref in ("\"C5\"", "\"C6\"")
)
checks["active_bom_excludes_optional_c7_c8"] = '"C7"' not in bom and '"C8"' not in bom
a1_hash = sha(parent / "lamp_buck_lmr51450_a1" / "lamp_buck_lmr51450_a1.kicad_pcb")
checks["a1_source_board_preserved"] = a1_hash == "8de29c7087512ae55a44a610edab968809a41a53c3724093b3f314c8405b06f3"

if not all(checks.values()):
    raise SystemExit(json.dumps(checks, indent=2))

result = {
    "status": "LOCAL_CAD_VALIDATION_PASS_PHYSICAL_AND_MANUFACTURING_HOLD",
    "candidate": "AI lamp LMR51450 output capacitor cost-down A2",
    "board_sha256": board_sha,
    "schematic_sha256": sha(schematic),
    "netlist_sha256": sha(netlist),
    "drc_violations": 0,
    "unconnected_items": 0,
    "erc_errors": 0,
    "erc_warnings": 0,
    "expected_schematic_parity_notices": ["C10", "C9", "D1", "R5"],
    "pad_count": parity.get("board_pad_count"),
    "pad_net_mismatches": 0,
    "footprints": parity.get("board_footprint_count"),
    "tracks": parity.get("board_track_count"),
    "vias": parity.get("board_via_count"),
    "selected_high_current_path_widths_mm": parity.get("selected_high_current_path_segment_widths_mm"),
    "5v_net_min_trace_width_mm": parity.get("sys_5v_net_min_width_mm"),
    "physical_validation": "NOT_RUN_NO_SAMPLE",
    "manufacturing_status": "FABRICATION_HOLD",
    "checks": checks,
}
(root / "A2-validation.json").write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
change_path = root / "board-change.json"
change = json.loads(change_path.read_text(encoding="utf-8"))
change["status"] = result["status"]
change["validation"] = {key: result[key] for key in ("drc_violations", "unconnected_items", "erc_errors", "erc_warnings", "physical_validation", "manufacturing_status")}
change_path.write_text(json.dumps(change, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
print(json.dumps(result, ensure_ascii=False, indent=2))
