"""Fresh producer rebuild, independent replay, byte comparison, and tests.

Run from any directory. All working inputs are in this ZIP; the fresh
producer does not read the shipped answers. A failed step exits nonzero.
"""
import argparse
import hashlib
import json
import os
import subprocess
import sys
import tempfile
from datetime import datetime, timezone
from pathlib import Path

ROOT = Path(__file__).resolve().parent
CORE_FILES = ("eigenline_certificate.json", "log_tables.json",
              "kurihara_certificate.json", "kurihara_terms.csv")


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


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--report", type=Path, default=ROOT/"results"/"fresh_replay.json")
    args = parser.parse_args()
    report = {"schema": "kurihara-fresh-replay-v1", "verdict": "RUNNING",
              "started_utc": datetime.now(timezone.utc).isoformat(), "steps": []}
    environment = dict(os.environ)
    environment["PYTHONHASHSEED"] = "0"
    environment["PYTHONNOUSERSITE"] = "1"
    environment["OPENBLAS_NUM_THREADS"] = "1"

    def execute(name, command):
        print(f"{name}: running", flush=True)
        completed = subprocess.run(command, cwd=ROOT, env=environment,
                                   capture_output=True, text=True, timeout=180)
        report["steps"].append({"step": name, "returncode": completed.returncode,
                                "stdout": completed.stdout, "stderr": completed.stderr})
        if completed.returncode:
            raise RuntimeError(f"{name}: exit {completed.returncode}")
        print(f"{name}: PASS", flush=True)
        return completed

    try:
        with tempfile.TemporaryDirectory(prefix="kurihara-fresh-") as temporary:
            fresh = Path(temporary)/"results"
            execute("C1_FRESH_PRODUCER", [sys.executable, str(ROOT/"src/build_certificate.py"),
                                         "--output", str(fresh)])
            execute("C2_INDEPENDENT_FULL_REPLAY", [sys.executable, str(ROOT/"src/verify_independent.py"),
                                                  "--results", str(fresh),
                                                  "--report", str(fresh/"independent_verification.json")])
            independent = json.loads((fresh/"independent_verification.json").read_text())
            if independent.get("verdict") != "PASS":
                raise RuntimeError("C2_INDEPENDENT_FULL_REPLAY: no positive verdict")
            report["independent_verification"] = independent
            comparisons = {}
            for filename in CORE_FILES:
                wanted, observed = digest(ROOT/"results"/filename), digest(fresh/filename)
                comparisons[filename] = {"shipped_sha256": wanted, "fresh_sha256": observed,
                                         "identical": wanted == observed}
                if wanted != observed:
                    raise RuntimeError(f"C3_BYTE_COMPARISON: {filename}")
            report["core_file_comparisons"] = comparisons
            report["fresh_producer_events"] = json.loads((fresh/"producer_events.json").read_text())
            report["fresh_environment"] = json.loads((fresh/"environment.json").read_text())
            print("C3_BYTE_COMPARISON: PASS", flush=True)
            execute("C4_PRIOR_INPUTS", [sys.executable, str(ROOT/"src/replay_prior_inputs.py"),
                                        "--report", str(fresh/"prior_input_replay.json")])
            report["prior_input_replay"] = json.loads((fresh/"prior_input_replay.json").read_text())
            execute("C5_EXACT_AND_MUTATION_TESTS", [sys.executable, "-m", "unittest", "discover",
                                                   "-s", "tests", "-v"])
        report["verdict"] = "PASS"
    except Exception as exc:
        report["verdict"] = "FAIL"
        report["failed_step"] = str(exc)
        print(str(exc), file=sys.stderr, flush=True)
    report["finished_utc"] = datetime.now(timezone.utc).isoformat()
    report["source_sha256"] = {str(p.relative_to(ROOT)): digest(p)
                               for p in sorted([ROOT/"run_all.py", *ROOT.glob("src/*.py"),
                                                *ROOT.glob("provenance/*.py"),
                                                *ROOT.glob("tests/*.py")])}
    args.report.parent.mkdir(parents=True, exist_ok=True)
    args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)+"\n",
                           encoding="utf-8")
    print(f"REPLAY {report['verdict']}", flush=True)
    return 0 if report["verdict"] == "PASS" else 1


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