import json
import math
import os
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_second_operator_capped_test.json"
OUTPUT_REPORT = ROOT / "results" / "row20_h0_attribution" / "row20_second_operator_capped_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 sign(x, eps=1e-9):
    if x > eps:
        return "+"
    if x < -eps:
        return "-"
    return "0"


def main():
    data = load(INPUT_FIRST)

    r = data["transformed_residual_vector"]

    desired_b2 = abs(r["r_SN"])
    early_cap = min(r["r_ell_A"], r["r_H_BAO"])

    # Lawful capped second bridge:
    # desired by SN pivot, capped by weakest positive early/radial residual.
    b2 = min(desired_b2, early_cap)

    transformed2 = {
        "r_ell_A": r["r_ell_A"] - b2,
        "r_H_BAO": r["r_H_BAO"] - b2,
        "r_D_M_BAO": r["r_D_M_BAO"],
        "r_SN": r["r_SN"] + b2,
        "r_SH0ES": r["r_SH0ES"] + b2,
    }

    original_vals = list(r.values())
    transformed_vals = list(transformed2.values())

    original_rss = rss(original_vals)
    transformed_rss = rss(transformed_vals)

    original_chi2 = chi2(original_vals)
    transformed_chi2 = chi2(transformed_vals)

    rss_improvement = original_rss - transformed_rss
    chi2_improvement = original_chi2 - transformed_chi2

    original_signs = {k: sign(v) for k, v in r.items()}
    transformed_signs = {k: sign(v) for k, v in transformed2.items()}

    no_forbidden_flip = (
        transformed2["r_ell_A"] >= -1e-9
        and transformed2["r_H_BAO"] >= -1e-9
        and abs(transformed2["r_D_M_BAO"]) < 1e-9
        and transformed2["r_SN"] <= 1e-9
        and transformed2["r_SH0ES"] <= 1e-9
    )

    tests = {
        "desired_anchor_is_SN": desired_b2 == abs(r["r_SN"]),
        "cap_is_weakest_early_radial_node": b2 == early_cap,
        "no_forbidden_flip": no_forbidden_flip,
        "BAO_H_saturates_to_zero": abs(transformed2["r_H_BAO"]) < 1e-9,
        "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 = "capped_second_operator_supported"
    elif score >= 4 and rss_improvement > 0:
        status = "capped_second_operator_partial"
    else:
        status = "capped_second_operator_not_supported"

    interpretation = [
        "Second operator is SN-pivot desired but capped by the weakest remaining early/radial residual.",
        "This prevents BAO H from flipping sign while still reducing the late/transverse side.",
        "If supported, this indicates a constrained multi-layer resolution path rather than an unrestricted fit."
    ]

    result = {
        "signature": "ROW20_SECOND_OPERATOR_CAPPED_TEST_v1",
        "context": "DIAGNOSTIC_NON_GATING",
        "desired_b2_SN_anchor": desired_b2,
        "early_radial_cap": early_cap,
        "applied_b2": b2,
        "input_residual_vector": r,
        "transformed_residual_vector": transformed2,
        "original_rss": original_rss,
        "transformed_rss": transformed_rss,
        "rss_improvement": rss_improvement,
        "original_chi2": original_chi2,
        "transformed_chi2": transformed_chi2,
        "chi2_improvement": chi2_improvement,
        "original_signs": original_signs,
        "transformed_signs": transformed_signs,
        "tests": tests,
        "score": score,
        "max_score": max_score,
        "interpretation": interpretation,
        "verdict": f"{status}; diagnostic only; no physics or parameter changes."
    }

    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 v21 — Capped Second Operator Test\n\n")
        f.write("## Operator\n\n")
        f.write("| Quantity | Value |\n")
        f.write("|---|---:|\n")
        f.write(f"| desired b2 from SN pivot | {desired_b2:.6f} |\n")
        f.write(f"| early/radial cap | {early_cap:.6f} |\n")
        f.write(f"| applied b2 | {b2:.6f} |\n\n")

        f.write("## Residual transformation\n\n")
        f.write("| Node | Before | After | Before sign | After sign |\n")
        f.write("|---|---:|---:|---:|---:|\n")
        for k in r:
            f.write(
                f"| {k} | {r[k]:.6f} | {transformed2[k]:.6f} | "
                f"{original_signs[k]} | {transformed_signs[k]} |\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("Capped second operator test:")
    print(f"desired_b2={desired_b2:.6f}")
    print(f"early_cap={early_cap:.6f}")
    print(f"applied_b2={b2:.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()