import json
import math
from pathlib import Path

ROOT = Path(".")

INPUT_FIRST = ROOT / "results" / "row20_h0_attribution" / "row20_NZ_CFGL_bridge_operator.json"

OUTPUT_JSON = ROOT / "results" / "row20_h0_attribution" / "row20_cross_layer_coupling_test.json"
OUTPUT_REPORT = ROOT / "results" / "row20_h0_attribution" / "row20_cross_layer_coupling_test.md"


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


def rss(vals):
    return math.sqrt(sum(v * v for v in vals))


def chi2(vals):
    return sum(v * v for v in vals)


def main():
    data = load(INPUT_FIRST)
    r = data["transformed_residual_vector"]

    # After first NZ/CFGL bridge:
    # BAO H is the guardrail. It caps how much early-side reduction can occur.
    ell = r["r_ell_A"]
    bao_h = r["r_H_BAO"]
    bao_dm = r["r_D_M_BAO"]
    sn = r["r_SN"]
    sh0es = r["r_SH0ES"]

    original = {
        "r_ell_A": ell,
        "r_H_BAO": bao_h,
        "r_D_M_BAO": bao_dm,
        "r_SN": sn,
        "r_SH0ES": sh0es,
    }

    original_rss = rss(original.values())
    original_chi2 = chi2(original.values())

    # Desired acoustic-distance transfer:
    # use late-distance mean pull magnitude as desired transfer,
    # but cap by BAO H so radial guardrail does not flip.
    late_mean_abs = (abs(sn) + abs(sh0es)) / 2.0
    guardrail_cap = bao_h

    applied_coupling = min(late_mean_abs, guardrail_cap)

    transformed = {
        "r_ell_A": ell - applied_coupling,
        "r_H_BAO": bao_h - applied_coupling,
        "r_D_M_BAO": bao_dm,
        "r_SN": sn + applied_coupling,
        "r_SH0ES": sh0es + applied_coupling,
    }

    transformed_rss = rss(transformed.values())
    transformed_chi2 = chi2(transformed.values())

    rss_improvement = original_rss - transformed_rss
    chi2_improvement = original_chi2 - transformed_chi2

    no_guardrail_break = (
        transformed["r_ell_A"] >= 0
        and transformed["r_H_BAO"] >= -1e-9
        and abs(transformed["r_D_M_BAO"]) < 1e-9
        and transformed["r_SN"] <= 0
        and transformed["r_SH0ES"] <= 0
    )

    tests = {
        "late_distance_mean_used_as_desired_transfer": late_mean_abs > 0,
        "BAO_H_guardrail_cap_applied": applied_coupling == guardrail_cap,
        "no_guardrail_break": no_guardrail_break,
        "rss_improves": rss_improvement > 0,
        "chi2_improves": chi2_improvement > 0,
    }

    score = sum(1 for v in tests.values() if v)
    max_score = len(tests)

    if score == max_score and rss_improvement > 0.5:
        status = "cross_layer_coupling_supported_but_guardrail_limited"
    elif score >= 4 and rss_improvement > 0:
        status = "cross_layer_coupling_weak_guardrail_limited"
    else:
        status = "cross_layer_coupling_not_supported"

    result = {
        "signature": "ROW20_CROSS_LAYER_COUPLING_TEST_v1",
        "context": "DIAGNOSTIC_NON_GATING",
        "input_residuals": original,
        "late_distance_mean_abs": late_mean_abs,
        "BAO_H_guardrail_cap": guardrail_cap,
        "applied_coupling": applied_coupling,
        "transformed_residuals": transformed,
        "original_rss": original_rss,
        "transformed_rss": transformed_rss,
        "rss_improvement": rss_improvement,
        "original_chi2": original_chi2,
        "transformed_chi2": transformed_chi2,
        "chi2_improvement": chi2_improvement,
        "tests": tests,
        "score": score,
        "max_score": max_score,
        "verdict": f"{status}; diagnostic only; no physics, thresholds, datasets, or gate verdicts changed.",
    }

    OUTPUT_JSON.parent.mkdir(parents=True, exist_ok=True)

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

    with open(OUTPUT_REPORT, "w", encoding="utf-8") as f:
        f.write("# UTFANSWF v22 — Cross-Layer Acoustic/Distance Coupling Test\n\n")
        f.write("**Context:** DIAGNOSTIC_NON_GATING\n\n")

        f.write("## Coupling\n\n")
        f.write("| Quantity | Value |\n")
        f.write("|---|---:|\n")
        f.write(f"| late-distance desired transfer | {late_mean_abs:.6f} |\n")
        f.write(f"| BAO H guardrail cap | {guardrail_cap:.6f} |\n")
        f.write(f"| applied coupling | {applied_coupling:.6f} |\n\n")

        f.write("## Residual transformation\n\n")
        f.write("| Node | Before | After |\n")
        f.write("|---|---:|---:|\n")
        for k in original:
            f.write(f"| {k} | {original[k]:.6f} | {transformed[k]:.6f} |\n")

        f.write("\n## Metrics\n\n")
        f.write("| Quantity | Value |\n")
        f.write("|---|---:|\n")
        f.write(f"| RSS before | {original_rss:.6f} |\n")
        f.write(f"| RSS after | {transformed_rss:.6f} |\n")
        f.write(f"| RSS improvement | {rss_improvement:.6f} |\n")
        f.write(f"| chi2 before | {original_chi2:.6f} |\n")
        f.write(f"| chi2 after | {transformed_chi2:.6f} |\n")
        f.write(f"| chi2 improvement | {chi2_improvement:.6f} |\n\n")

        f.write("## Tests\n\n")
        for k, v in tests.items():
            f.write(f"- {k}: {v}\n")

        f.write(f"\nScore: {score}/{max_score}\n")
        f.write(f"Verdict: {status}\n")

    print("Cross-layer coupling test:")
    print(f"late desired={late_mean_abs:.6f}")
    print(f"BAO H cap={guardrail_cap:.6f}")
    print(f"applied={applied_coupling:.6f}")
    print(f"RSS before={original_rss:.6f}")
    print(f"RSS after={transformed_rss:.6f}")
    print(f"RSS improvement={rss_improvement:.6f}")
    print(f"score={score}/{max_score}")
    print(f"status={status}")


if __name__ == "__main__":
    main()