from __future__ import annotations

import datetime
import json
import math
import os

import pandas as pd

from .common import sha256_file


def _utc_now_z() -> str:
    return datetime.datetime.now(datetime.UTC).isoformat(timespec="seconds").replace("+00:00", "Z")


def gate_jwst_diagnostic(root: str) -> dict:
    spec_path = os.path.join(root, "datasets", "jwst_diagnostic_v23.json")
    with open(spec_path, "r", encoding="utf-8") as f:
        spec = json.load(f)

    inp = spec["active_diagnostic_inputs"]
    data_path = os.path.join(root, *inp["data"].split("/"))
    theory_path = os.path.join(root, *inp["theory"].split("/"))

    data_hash = sha256_file(data_path)
    theory_hash = sha256_file(theory_path)

    data = pd.read_csv(data_path)
    theory = pd.read_csv(theory_path)
    df = data.merge(theory, on="Muv", how="inner", validate="one_to_one")

    residual = df["y_data"].to_numpy(dtype=float) - df["y_th"].to_numpy(dtype=float)
    sigma = df["sigma"].to_numpy(dtype=float)
    chi2 = float(((residual / sigma) ** 2).sum())
    n = int(len(df))
    chi2_over_n = chi2 / n
    rms = float(math.sqrt(float((residual ** 2).mean())))

    hist = spec["historical_metrics"]
    checks = {
        "data_hash_matches_archived_ledger": data_hash == inp["data_sha256"],
        "theory_hash_matches_archived_ledger": theory_hash == inp["theory_sha256"],
        "eight_point_diagnostic_recovered": n == int(hist["nu_assumed"]),
        "chi2_reproduces_archived_record": math.isclose(chi2, float(hist["chi2"]), rel_tol=0.0, abs_tol=1e-12),
        "chi2_over_n_reproduces_archived_record": math.isclose(chi2_over_n, float(hist["chi2_over_nu"]), rel_tol=0.0, abs_tol=1e-12),
        "rms_reproduces_archived_record": math.isclose(rms, float(hist["rms_residual"]), rel_tol=0.0, abs_tol=1e-12),
        "historical_pass_status_remains_undecided": hist["pass_status"] == "UNDECIDED_NO_EXPLICIT_STANDALONE_THRESHOLD",
        "physical_jwst_pass_not_claimed": spec["claim_boundary"]["physical_jwst_gate_pass_claimed"] is False,
        "manuscript_1p102_not_silently_promoted": spec["manuscript_history"]["reproduced_from_current_bundle"] is False,
    }
    record_pass = all(checks.values())

    return {
        "row": 20.4,
        "gate": "jwst_uvlf_diagnostic_record",
        "context": "POST_RELEASE_HARDENING",
        "tier": "Diagnostic",
        "timestamp_utc": _utc_now_z(),
        "blocking": False,
        "verdict": "PASS" if record_pass else "FAIL",
        "status": "PASS_JWST_DIAGNOSTIC_REPRODUCTION__PHYSICAL_GATE_OPEN" if record_pass else "FAIL_JWST_DIAGNOSTIC_RECORD_INTEGRITY",
        "metrics": {
            "n_points": n,
            "chi2": chi2,
            "chi2_over_n_historical_nu_assumption": chi2_over_n,
            "rms_residual": rms,
        },
        "checks": checks,
        "claim_boundary": {
            "record_integrity_pass_is_physical_jwst_pass": False,
            "standalone_jwst_acceptance_threshold_present_in_archived_run": False,
            "full_uvlf_sfrd_stellar_mass_sizes_lines_pipeline_executed": False,
            "manuscript_historical_chi2_over_nu_1p102_reproduced": False,
            "physical_jwst_status": "OPEN",
        },
        "inputs": {
            "data": inp["data"],
            "theory": inp["theory"],
            "hashes": {
                "data": data_hash,
                "theory": theory_hash,
                "spec": sha256_file(spec_path),
            },
        },
        "notes": "Reproduces the archived eight-point JWST UVLF diagnostic exactly. The source archive declared no standalone PASS threshold; physical JWST validation remains open."
    }


def main() -> None:
    root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
    out_dir = os.path.join(root, "results", "row20_4_jwst")
    os.makedirs(out_dir, exist_ok=True)
    res = gate_jwst_diagnostic(root)
    with open(os.path.join(out_dir, "result.json"), "w", encoding="utf-8") as f:
        json.dump(res, f, indent=2, sort_keys=True)
    print(json.dumps(res, indent=2, sort_keys=True))


if __name__ == "__main__":
    main()
