import json
import math
import os
from pathlib import Path

ROOT = Path(".")

INPUT_OWNERSHIP = ROOT / "results" / "row20_h0_attribution" / "row20_bridge_theory_ownership.json"
INPUT_ANCHORED = ROOT / "results" / "row20_h0_attribution" / "row20_BAO_DM_anchored_bridge.json"
INPUT_SIGN = ROOT / "results" / "row20_h0_attribution" / "row20_layered_sign_consistency.json"

OUTPUT_JSON = ROOT / "results" / "row20_h0_attribution" / "row20_bridge_UTFANSWF_mapping_test.json"
OUTPUT_REPORT = ROOT / "results" / "row20_h0_attribution" / "row20_bridge_UTFANSWF_mapping_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 main():
    ownership = load(INPUT_OWNERSHIP)
    anchored = load(INPUT_ANCHORED)
    sign_data = load(INPUT_SIGN)

    original = anchored["original_residuals"]
    transformed = anchored["transformed_residuals"]

    bridge_strength = anchored["bridge_strength"]

    # UTFANSWF mapping signatures:
    # 1. NZ neutralization: bridge neutralizes BAO_D_M transverse node.
    # 2. CFGL directionality: early/radial positive nodes decrease; late/transverse negative nodes increase toward zero.
    # 3. Observer/projection balance: both layer groups improve with balance ratio high.
    # 4. No gate cheating: no sign-pattern destruction or hidden parameter.
    # 5. Existing-source bridge: strength comes from BAO_D_M, not fitted optimum.

    nz_neutralization = abs(transformed["BAO_D_M"]) < 1e-9

    cfgl_directionality = (
        transformed["CMB_ell_A"] < original["CMB_ell_A"]
        and transformed["BAO_H"] < original["BAO_H"]
        and transformed["SN_pivot"] > original["SN_pivot"]
        and transformed["SH0ES"] > original["SH0ES"]
    )

    observer_projection_balance = (
        ownership["group_metrics"]["early_radial"]["improvement"] > 0
        and ownership["group_metrics"]["late_transverse"]["improvement"] > 0
        and ownership["group_metrics"]["balance_ratio"] >= 0.75
    )

    no_gate_cheating = (
        anchored["no_forbidden_flip"] is True
        and anchored["rss_improvement"] > 2.0
    )

    existing_source_bridge = (
        anchored["bridge_strength_source"] == "abs(BAO_D_M_z0_706_pull)"
    )

    tests = {
        "NZ_neutralization_BAO_DM": nz_neutralization,
        "CFGL_directionality": cfgl_directionality,
        "observer_projection_balance": observer_projection_balance,
        "no_gate_cheating": no_gate_cheating,
        "existing_source_bridge": existing_source_bridge,
    }

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

    if score == max_score:
        status = "UTFANSWF_bridge_mapping_strong_candidate"
    elif score >= 4:
        status = "UTFANSWF_bridge_mapping_partial_candidate"
    else:
        status = "UTFANSWF_bridge_mapping_weak"

    interpretation = []

    interpretation.append(
        "This diagnostic tests whether the BAO-D_M anchored bridge behaves like an existing UTFANSWF layered transfer."
    )

    if nz_neutralization:
        interpretation.append(
            "NZ signature: the bridge neutralizes the transverse BAO D_M node, matching a neutral-zone cancellation behavior."
        )

    if cfgl_directionality:
        interpretation.append(
            "CFGL signature: the bridge moves early/radial and late/transverse sectors toward reduced residuals in opposite but coherent directions."
        )

    if observer_projection_balance:
        interpretation.append(
            "Observer/projection signature: both layer groups improve with high balance, supporting a coupled projection interpretation."
        )

    if existing_source_bridge:
        interpretation.append(
            "The bridge strength is sourced from an existing observable residual, not from a newly introduced parameter."
        )

    if score == max_score:
        interpretation.append(
            "All mapping signatures pass. This supports a UTFANSWF-native bridge candidate, pending formal equation-level derivation."
        )
    else:
        interpretation.append(
            "Mapping signatures are incomplete; bridge ownership remains provisional."
        )

    result = {
        "signature": "ROW20_BRIDGE_UTFANSWF_MAPPING_TEST_v1_NATIVE_DIAGNOSTIC",
        "context": "DIAGNOSTIC_NON_GATING",
        "bridge_strength": bridge_strength,
        "tests": tests,
        "score": score,
        "max_score": max_score,
        "original_residuals": original,
        "transformed_residuals": transformed,
        "group_metrics": ownership["group_metrics"],
        "interpretation": interpretation,
        "verdict": (
            f"{status}; diagnostic only; no physics, thresholds, datasets, "
            "parameters, 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 v21 — Bridge to UTFANSWF Mapping Test\n\n")
        f.write("**Context:** DIAGNOSTIC_NON_GATING. No physics, thresholds, datasets, parameters, or gate verdicts changed.\n\n")

        f.write("## Bridge\n\n")
        f.write("| Quantity | Value |\n")
        f.write("|---|---:|\n")
        f.write(f"| bridge strength | {bridge_strength:.6f} |\n")
        f.write(f"| bridge source | {anchored['bridge_strength_source']} |\n")
        f.write(f"| RSS improvement | {anchored['rss_improvement']:.6f} |\n\n")

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

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

        f.write("## Residual transformation\n\n")
        f.write("| Node | Original pull σ | Transformed pull σ |\n")
        f.write("|---|---:|---:|\n")
        for k in original:
            f.write(f"| {k} | {original[k]:.6f} | {transformed[k]:.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_JSON))
    print(os.path.abspath(OUTPUT_REPORT))
    print()
    print("UTFANSWF bridge mapping test:")
    print(f"score={score}/{max_score}")
    print(f"bridge strength={bridge_strength:.6f}")
    print(f"status={status}")


if __name__ == "__main__":
    main()