"""Reproduce the constrained solar candidate from a clean extracted package."""
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import sys
import numpy as np

BASE=Path(__file__).resolve().parent


def run(name,*args):
    command=[sys.executable,"-B","-W","error",name,*args]
    print("Running "+" ".join(command),flush=True)
    subprocess.run(command,cwd=BASE,check=True)


def close(actual,expected,relative=2e-7,absolute=0.):
    assert np.isclose(actual,expected,rtol=relative,atol=absolute),(actual,expected)


def main():
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--full",action="store_true",help="Repeat every solar field, numerical control and Green extraction")
    args=parser.parse_args()
    manifest=BASE/"manifest.json"
    if manifest.exists():
        for name,expected in json.loads(manifest.read_text())["sha256"].items():
            assert hashlib.sha256((BASE/name).read_bytes()).hexdigest()==expected,name
    run("build_cmc_solver.py")
    run("dark_cmc_theory.py")
    run("dark_cmc_variation.py")
    run("dark_cmc_3d.py")
    run("dark_cmc_model.py","--stage","pilot")
    expected=json.loads((BASE/"expected/publication_summary.json").read_text())
    theory=json.loads((BASE/"outputs/dark_cmc/theory_summary.json").read_text())
    pilot=json.loads((BASE/"outputs/dark_cmc/pilot_summary.json").read_text())
    pilot_expected=json.loads((BASE/"expected/pilot_summary.json").read_text())
    close(theory["candidate"]["rar_rms_dex"],expected["candidate"]["rar_rms_dex"],1e-11)
    close(pilot["cases"][0]["solar"]["result"]["Q2_s_minus2"][1],
          pilot_expected["cases"][0]["solar"]["result"]["Q2_s_minus2"][1],absolute=1e-32)
    three=json.loads((BASE/"outputs/dark_cmc/3d_summary.json").read_text())
    assert three["fields"][-1]["relative_residual"]<2e-9
    close(three["fields"][-1]["refinement_gradient_relative_L2"],
          expected["numerical_controls"]["three_dimensional_final"]["refinement_gradient_relative_L2"],relative=2e-5)
    if args.full:
        for stage in ["fields","controls","ir"]:
            run("dark_cmc_model.py","--stage",stage)
        run("dark_cmc_solar_checks.py")
        run("dark_cmc_inner_check.py")
        run("dark_cmc_report.py")
        actual=json.loads((BASE/"outputs/dark_cmc/publication_summary.json").read_text())
        for a,b in zip(actual["external_field_cases"],expected["external_field_cases"],strict=True):
            close(a["Q2_s_minus2"],b["Q2_s_minus2"],absolute=1e-32)
            close(a["additional_precession_envelope_arcsec_century"],b["additional_precession_envelope_arcsec_century"],relative=2e-5)
        assert actual["all_sampled_marginal_screens_pass"]
    result={"mode":"full" if args.full else "quick","passed":True,
            "scope":"Physical tolerances checked; runtime, compiler binaries and compressed-field bytes may differ"}
    (BASE/"outputs/dark_cmc/reproduction_check.json").write_text(json.dumps(result,indent=2)+"\n")
    print(json.dumps(result),flush=True)


if __name__=="__main__":
    main()
