#!/usr/bin/env python3
"""Run XDVD sidecar auth controls for GDR-8050L.

v100 matrix:
  1) locked_control: post-auth sidecar state remains locked. Capacity should not change.
  2) forced_unlocked: post-auth sidecar state is unlocked. Capacity should change, proving sidecar/data-in plumbing only.

This script does not prove firmware authentication. It separates emulator plumbing from auth-state proof.
"""
from __future__ import annotations

import argparse, json, subprocess, sys
from pathlib import Path

VERSION = "v100"


def run_seq(ns: argparse.Namespace, label: str, post_state: str) -> Path:
    script = Path(__file__).resolve().parent / "run_gdr_auth_sequence.py"
    out_prefix = f"{ns.out_prefix}_{label}"
    cmd = [
        ns.python, str(script),
        "--workspace", str(ns.workspace),
        "--bin", str(ns.bin),
        "--xdvd-sidecar", str(ns.xdvd_sidecar),
        "--out-prefix", out_prefix,
        "--max-cycles", str(ns.max_cycles),
        "--xdvd-post-state", post_state,
    ]
    if ns.iso:
        cmd += ["--iso", str(ns.iso)]
    if ns.continue_after_timer:
        cmd += ["--continue-after-timer"]
    if ns.minimal:
        cmd += ["--minimal"]
    print("\n[MATRIX-RUN] " + label + " post_state=" + post_state)
    print("[RUN] " + " ".join(cmd), flush=True)
    rc = subprocess.run(cmd).returncode
    if rc != 0:
        raise SystemExit(rc)
    return Path(f"{out_prefix}_read_capacity_compare_v100.json")


def load_changed(path: Path) -> tuple[bool | None, str]:
    if not path.exists():
        return None, "missing"
    data = json.loads(path.read_text(encoding="utf-8"))
    before = data.get("before", {})
    after = data.get("after", {})
    msg = f"before={before.get('first_8_hex')} after={after.get('first_8_hex')} changed={data.get('changed')} meaningful={data.get('meaningful_capacity_change_candidate')}"
    return bool(data.get("changed")), msg


def main(argv: list[str]) -> int:
    ap = argparse.ArgumentParser(description="Run locked-vs-forced-unlocked XDVD sidecar control matrix")
    ap.add_argument("--workspace", required=True, type=Path)
    ap.add_argument("--bin", required=True, type=Path)
    ap.add_argument("--xdvd-sidecar", required=True, type=Path)
    ap.add_argument("--iso", type=Path)
    ap.add_argument("--out-prefix", default="xdvd_auth_matrix_v100")
    ap.add_argument("--max-cycles", type=int, default=160000)
    ap.add_argument("--continue-after-timer", action="store_true")
    ap.add_argument("--minimal", action="store_true", help="run shorter sequence for quick plumbing checks")
    ap.add_argument("--python", default=sys.executable)
    ns = ap.parse_args(argv[1:])

    locked_json = run_seq(ns, "locked_control", "locked")
    forced_json = run_seq(ns, "forced_unlocked", "unlocked")

    locked_changed, locked_msg = load_changed(locked_json)
    forced_changed, forced_msg = load_changed(forced_json)
    summary = {
        "tool": "run_xdvd_auth_matrix.py",
        "version": VERSION,
        "locked_control": {"path": str(locked_json), "changed": locked_changed, "summary": locked_msg},
        "forced_unlocked": {"path": str(forced_json), "changed": forced_changed, "summary": forced_msg},
        "interpretation": [],
    }
    if locked_changed is False and forced_changed is True:
        summary["interpretation"].append("PASS: sidecar/data-in plumbing distinguishes locked and unlocked capacities.")
        summary["interpretation"].append("Auth proof still requires a non-forced persistent firmware/session transition.")
    elif locked_changed is True:
        summary["interpretation"].append("WARNING: locked control changed capacity; sidecar state handling is not isolated.")
    elif forced_changed is False:
        summary["interpretation"].append("WARNING: forced-unlocked control did not change capacity; sidecar/data-in plumbing is incomplete.")
    out = Path(f"{ns.out_prefix}_matrix_summary_v100.json")
    out.write_text(json.dumps(summary, indent=2), encoding="utf-8")
    print("\n[MATRIX-SUMMARY]")
    print("[LOCKED] " + locked_msg)
    print("[FORCED] " + forced_msg)
    for line in summary["interpretation"]:
        print("[RESULT] " + line)
    print(f"[OK] wrote {out}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
