#!/usr/bin/env python3
"""Run the complete F01 build twice and prove byte-identical generated outputs."""

from __future__ import annotations

import hashlib
import json
import subprocess
import sys
from pathlib import Path


ANALYSIS = Path(__file__).resolve().parent
ROOT = ANALYSIS.parent
VALIDATION = ANALYSIS / "validation"


def sha256(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def generated_manifest() -> dict[str, str]:
    paths = sorted((ANALYSIS / "processed").glob("*")) + sorted((ROOT / "FIGURES").glob("*.svg")) + [ROOT / "FIGURES" / "FIGURE_MANIFEST.csv"]
    return {
        str(path.relative_to(ROOT)): sha256(path)
        for path in paths
        if path.is_file() and path.name not in {"DETERMINISM_REPORT.json"}
    }


def write_manifest(path: Path, manifest: dict[str, str]) -> None:
    path.write_text("".join(f"{digest}  {name}\n" for name, digest in sorted(manifest.items())), encoding="utf-8")


def main() -> None:
    VALIDATION.mkdir(parents=True, exist_ok=True)
    runs = []
    for index in (1, 2):
        completed = subprocess.run(
            [sys.executable, str(ANALYSIS / "reproduce.py")],
            cwd=ROOT,
            check=True,
            text=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
        )
        manifest = generated_manifest()
        write_manifest(VALIDATION / f"determinism_run_{index}.sha256", manifest)
        (VALIDATION / f"determinism_run_{index}.log").write_text(completed.stdout, encoding="utf-8")
        runs.append(manifest)
    differing = sorted(name for name in set(runs[0]) | set(runs[1]) if runs[0].get(name) != runs[1].get(name))
    report = {
        "status": "pass" if not differing else "fail",
        "runs": 2,
        "files_compared": len(set(runs[0]) | set(runs[1])),
        "differing_files": differing,
        "scope": "BEA XLSX extraction plus all processed CSV/JSON and SVG outputs",
    }
    (VALIDATION / "DETERMINISM_REPORT.json").write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8")
    print(json.dumps(report, indent=2, sort_keys=True))
    if differing:
        raise SystemExit(1)


if __name__ == "__main__":
    main()
