import json
import os
import math

INPUT_FILE = "results/row20_h0_attribution/row20_thin_slice_attribution.json"
OUTPUT_FILE = "results/row20_h0_attribution/row20_lA_probe.json"
REPORT_FILE = "results/row20_h0_attribution/row20_lA_probe_REPORT.md"


def load_json(path):
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)


def find_block(data, tag):
    for block in data.get("blocks", []):
        if block.get("tag") == tag:
            return block
    raise ValueError(f"Block not found: {tag}")


def find_node(block, slice_name):
    for node in block.get("nodes", []):
        if node.get("slice") == slice_name:
            return node
    raise ValueError(f"Slice not found: {slice_name}")


def main():
    if not os.path.exists(INPUT_FILE):
        raise FileNotFoundError(f"Missing input file: {INPUT_FILE}")

    data = load_json(INPUT_FILE)

    cmb = find_block(data, "CMB")
    ell = find_node(cmb, "ell_A")

    data_val = ell["data"]
    theory_val = ell["theory"]
    residual = ell["residual_after_gate_handling"]
    sigma_diag = ell["sigma_diag"]
    diag_pull = ell["diag_pull_sigma"]
    white_chi2 = ell["white_chi2_contribution"]

    total_no_gw = data["totals"]["CMB_BAO_SN_no_GW"]
    locked = data["totals"]["locked_v21_with_GW"]

    # Required theory value to exactly hit ell_A observed value
    required_theory_shift = data_val - theory_val

    # Fractional shift in theory ell_A
    fractional_shift = required_theory_shift / theory_val

    # Approximate pull targets
    shifts = []
    for target_pull in [4, 3, 2, 1, 0]:
        target_residual = target_pull * sigma_diag
        target_theory = data_val - target_residual
        delta_theory = target_theory - theory_val
        shifts.append({
            "target_pull_sigma": target_pull,
            "required_theory_ell_A": target_theory,
            "delta_theory_from_current": delta_theory,
            "fractional_delta": delta_theory / theory_val,
            "approx_chi2": target_pull ** 2
        })

    interpretation = []

    if abs(diag_pull) >= 4:
        interpretation.append(
            "ell_A is a dominant high-pull node and is acting as the primary CMB-side anchor."
        )

    if abs(fractional_shift) < 0.002:
        interpretation.append(
            "The fractional theory shift needed to remove the ell_A residual is small in absolute percentage terms."
        )
    else:
        interpretation.append(
            "The fractional theory shift needed to remove the ell_A residual is not negligible."
        )

    if locked["chi2_per_dof"] <= data["threshold_reference_chi2_per_dof"]:
        interpretation.append(
            "Locked v21 still passes under released full accounting, but ell_A dominates the cosmology-only stress."
        )

    result = {
        "signature": "ROW20_LA_PROBE_v1_NATIVE_DIAGNOSTIC",
        "context": "DIAGNOSTIC_NON_GATING",
        "rules": data.get("rules", {}),
        "H0_used_by_v21": data.get("H0_used_by_v21"),
        "ell_A": {
            "data": data_val,
            "theory": theory_val,
            "residual_data_minus_theory": residual,
            "sigma_diag": sigma_diag,
            "diag_pull_sigma": diag_pull,
            "white_chi2_contribution": white_chi2,
            "required_theory_shift_to_zero_residual": required_theory_shift,
            "fractional_required_shift": fractional_shift
        },
        "shift_table": shifts,
        "totals_reference": {
            "CMB_BAO_SN_no_GW": total_no_gw,
            "locked_v21_with_GW": locked
        },
        "interpretation": interpretation,
        "verdict": (
            "ell_A_DOMINANT_ANCHOR_OR_PROJECTION_STRESS; "
            "diagnostic only; no physics, threshold, dataset, parameter, or verdict changes."
        )
    }

    os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True)

    with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
        json.dump(result, f, indent=2)

    with open(REPORT_FILE, "w", encoding="utf-8") as f:
        f.write("# UTFANSWF v21 — Row 20 ell_A Probe\n\n")
        f.write("**Context:** DIAGNOSTIC_NON_GATING. No physics, thresholds, datasets, parameters, or gate verdicts changed.\n\n")
        f.write("## ell_A node\n\n")
        f.write("| Quantity | Value |\n")
        f.write("|---|---:|\n")
        f.write(f"| data | {data_val:.9f} |\n")
        f.write(f"| theory | {theory_val:.9f} |\n")
        f.write(f"| residual data-theory | {residual:.9f} |\n")
        f.write(f"| sigma_diag | {sigma_diag:.9f} |\n")
        f.write(f"| diag pull sigma | {diag_pull:.6f} |\n")
        f.write(f"| white chi2 contribution | {white_chi2:.6f} |\n")
        f.write(f"| required theory shift to zero residual | {required_theory_shift:.9f} |\n")
        f.write(f"| fractional required shift | {fractional_shift:.9e} |\n\n")

        f.write("## Pull reduction table\n\n")
        f.write("| Target pull | required theory ell_A | delta from current | fractional delta | approx chi2 |\n")
        f.write("|---:|---:|---:|---:|---:|\n")
        for row in shifts:
            f.write(
                f"| {row['target_pull_sigma']} | "
                f"{row['required_theory_ell_A']:.9f} | "
                f"{row['delta_theory_from_current']:.9f} | "
                f"{row['fractional_delta']:.9e} | "
                f"{row['approx_chi2']:.6f} |\n"
            )

        f.write("\n## Interpretation\n\n")
        for item in interpretation:
            f.write(f"- {item}\n")

        f.write("\n## Verdict\n\n")
        f.write(result["verdict"] + "\n")

    print("Wrote:")
    print(os.path.abspath(OUTPUT_FILE))
    print(os.path.abspath(REPORT_FILE))
    print()
    print("ell_A probe:")
    print(f"data={data_val:.9f}")
    print(f"theory={theory_val:.9f}")
    print(f"pull={diag_pull:.6f} sigma")
    print(f"required theory shift={required_theory_shift:.9f}")
    print(f"fractional shift={fractional_shift:.9e}")


if __name__ == "__main__":
    main()