#!/usr/bin/env python3
"""
verify_P096.py -- Addendum 96: G2 protection of the Jarlskog invariant.

This verifier checks the internal consistency of the paper's constants,
Jarlskog routes, and proof claims. P96 is unusual because the abstract still
states the A92 paired-correction/protection story, while the body later derives
the opposite uniform-rescaling result and explicitly resolves OP-P92-1 in the
negative.
"""

import math
import sys
from pathlib import Path

PASS = FAIL = 0
_N = 0


def check(n, desc, cond):
    global PASS, FAIL
    ok = bool(cond); PASS += ok; FAIL += (not ok)
    print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {desc}")
    return ok


class Verifier:
    """Target-style output adapter; check/record numerics are unchanged."""

    def __init__(self, name):
        print(name)

    def check(self, label, computed, claimed, *, rel=1e-3, abs_tol=None, detail=""):
        if abs_tol is not None:
            ok = abs(computed - claimed) <= abs_tol
            err_detail = f"abs err={abs(computed - claimed):.6g}, tol={abs_tol:.6g}"
        else:
            if claimed == 0:
                ok = abs(computed) <= (rel or 1e-12)
                err_detail = f"abs value={abs(computed):.6g}, tol={rel:.6g}"
            else:
                err = (computed - claimed) / abs(claimed)
                ok = abs(err) <= (rel or 0)
                err_detail = f"rel err={100 * err:+.6g}%, tol={100 * (rel or 0):.6g}%"
        return self.record(label, ok, computed, claimed,
                           err_detail + (f"; {detail}" if detail else ""))

    def record(self, label, ok, computed="", claimed="", detail=""):
        global _N
        ok = bool(ok)
        desc, extra = label, detail
        if not ok and detail:
            desc, extra = f"{label} -- {detail}", ""
        _N += 1
        check(_N, desc, ok)
        if computed != "" or claimed != "":
            print(f"       computed: {computed}")
            print(f"       claimed : {claimed}")
        if extra:
            print(f"       {extra}")
        return ok

    def summary(self):
        print(f"\n{'='*60}\nRESULT: {PASS} PASS / {FAIL} FAIL")
        return 1 if FAIL else 0


v = Verifier("P096 -- G2 3-Form Protection of the Jarlskog Invariant")

ROOT = Path(__file__).resolve().parents[1]
TEX = (ROOT / "96_Addendum_JarlskogProtection.tex").read_text()

PI = math.pi
LAM = math.sin(PI / 14)
LAM2 = LAM**2
LAM4 = LAM**4
LAM6 = LAM**6
F = 1 - 4 * LAM2 / 5
A_LO = math.cos(PI / 14) ** 2 * math.cos(2 * PI / 14)
A_NLO = A_LO * F
DELTA = 31 * PI / 84
PHI_LO = math.cos(PI / 14) * math.cos(2 * PI / 14) * math.cos(5 * PI / 28)
SIN_DELTA = math.sin(DELTA)
COS_DELTA = math.cos(DELTA)
COT_DELTA = COS_DELTA / SIN_DELTA
RHO_LO = 0.5 * PHI_LO * COS_DELTA
ETA_LO = 0.5 * PHI_LO * SIN_DELTA
J_LO = A_LO**2 * LAM6 * ETA_LO
PDG_J = 3.08e-5


def residual_pct(value: float, target: float) -> float:
    return 100 * (value - target) / target


v.check("lambda = sin(pi/14)", LAM, 0.22252, rel=5e-6)
v.check("lambda^2", LAM2, 0.04951, rel=2e-4)
v.check("lambda^4", LAM4, 0.002451, rel=5e-4)
v.check("lambda^6", LAM6, 1.2148e-4, rel=8e-4)
v.check("A_LO", A_LO, 0.8563, rel=1e-4)
v.check("NLO factor 1 - 4 lambda^2/5", F, 0.96039, rel=5e-6)
v.check("A_NLO", A_NLO, 0.8224, rel=5e-5)
v.check("delta_0 degrees", math.degrees(DELTA), 66.43, rel=3e-5)
v.check("sin(delta_0)", SIN_DELTA, 0.9162, rel=5e-4)
v.check("cos(delta_0)", COS_DELTA, 0.4008, rel=3e-3)
v.check("cot(delta_0)", COT_DELTA, 0.4375, rel=4e-3)

v.check(
    "Phi_LO from stated exact formula",
    PHI_LO,
    0.7429,
    rel=5e-4,
    detail="Expected fail: the printed exact formula gives about 0.743745, a stale value inherited from earlier CKM papers.",
)
v.check(
    "rho_LO from exact Phi and delta",
    RHO_LO,
    0.1484,
    rel=5e-4,
    detail="Expected fail: exact Phi and delta give about 0.148709.",
)
v.check(
    "eta_LO from exact Phi and delta",
    ETA_LO,
    0.3439,
    rel=5e-4,
    detail="Expected fail: exact Phi and delta give about 0.340844.",
)
v.check(
    "J_LO from exact stated formulas",
    J_LO,
    3.064e-5,
    rel=5e-4,
    detail="Expected fail: exact Phi-derived eta gives about 3.035e-5; 3.064e-5 uses the stale eta.",
)

# Abstract/A92 paired-correction route.
phi_up = PHI_LO * (1 + 8 * LAM2 / 5)
eta_up = 0.5 * phi_up * SIN_DELTA
rho_up = 0.5 * phi_up * COS_DELTA
j_abstract_exact = J_LO * (1 - 48 * LAM4 / 25)
j_paired_exact = A_NLO**2 * LAM6 * eta_up

v.check(
    "abstract paired Phi route eta_NLO",
    eta_up,
    0.3466,
    rel=2e-3,
    detail="Expected fail: applying the abstract's +8 lambda^2/5 Phi correction with unchanged phase gives about 0.36785, not 0.3466.",
)
v.check(
    "abstract paired Phi route rho_NLO",
    rho_up,
    0.1501,
    rel=2e-3,
    detail="Expected fail: applying the abstract's +8 lambda^2/5 Phi correction gives about 0.16049.",
)
v.check(
    "abstract exact J_LO*(1 - 48 lambda^4/25)",
    j_abstract_exact,
    3.053e-5,
    rel=5e-3,
    detail="Expected fail with exact inputs: this is about 3.020e-5; 3.053e-5 comes from rounded/stale J_LO.",
)
v.check(
    "abstract paired direct J route",
    j_paired_exact,
    3.053e-5,
    rel=5e-3,
    detail="Expected fail: exact paired direct substitution gives about 3.021e-5.",
)
v.check(
    "abstract claimed residual from claimed J",
    residual_pct(3.053e-5, PDG_J),
    -0.9,
    rel=5e-2,
)
v.check(
    "abstract formula residual with exact inputs",
    residual_pct(j_abstract_exact, PDG_J),
    -0.9,
    rel=5e-2,
    detail="Expected fail: exact inputs give about -1.94%, not -0.9%.",
)

# Body/uniform-rescaling route.
phi_down = PHI_LO * F
eta_down = 0.5 * phi_down * SIN_DELTA
rho_down = 0.5 * phi_down * COS_DELTA
j_down_exact = A_NLO**2 * LAM6 * eta_down
uniform_ratio = F**3
direct_rounded = 0.8224**2 * 1.2148e-4 * 0.3268
ratio_rounded = 3.064e-5 * 0.96039**3

v.check("body Phi_NLO = Phi_LO*(1 - 4 lambda^2/5)", phi_down, 0.7135, rel=2e-3)
v.check(
    "body eta_NLO from exact Phi path",
    eta_down,
    0.3303,
    rel=2e-3,
    detail="Expected fail: exact Phi-derived eta gives about 0.32734; 0.3303 uses the stale LO eta 0.3439.",
)
v.check("body rho_NLO from exact Phi path", rho_down, 0.1425, rel=3e-3)
v.check("proposition eta_NLO direct rounded value", eta_down, 0.3268, rel=3e-3)
v.check("proposition direct J_NLO product", direct_rounded, 2.684e-5, rel=5e-4)
v.check("uniform ratio F^3", uniform_ratio, 0.88575, rel=2e-4)
v.check("ratio route using rounded J_LO", ratio_rounded, 2.714e-5, rel=5e-4)
v.check(
    "exact uniform J_NLO vs final table value",
    j_down_exact,
    2.714e-5,
    rel=5e-3,
    detail="Expected fail: exact stated formulas give about 2.688e-5; 2.714e-5 uses rounded/stale J_LO.",
)
v.check(
    "exact uniform J residual vs PDG",
    residual_pct(j_down_exact, PDG_J),
    -11.8,
    rel=5e-2,
    detail="Expected fail: exact stated formulas give about -12.7%; -11.8% follows from the rounded ratio route.",
)
v.record(
    "direct and ratio J routes differ only by negligible rounding",
    abs(ratio_rounded - direct_rounded) / direct_rounded < 0.003,
    f"direct={direct_rounded:.6e}, ratio={ratio_rounded:.6e}",
    "rounding-level agreement",
    "Expected fail: the two printed routes differ by about 1.1%, too large for a four-significant-figure rounding note.",
)

# Proof-text consistency checks.
has_plus_phi = "1 + \\frac{8\\lambda^2}{5}" in TEX
has_minus_phi = "1 - \\frac{4\\lambda^2}{5}" in TEX
v.record(
    "abstract and body use one NLO Phi sign",
    not (has_plus_phi and has_minus_phi),
    "abstract has +8 lambda^2/5; body has -4 lambda^2/5",
    "single NLO Phi correction",
    "Expected fail: P96 contains both the A92 paired-increase route and the later uniform-decrease route.",
)

abstract_proved = "conjecture~5.3" in TEX[:5000].lower() and "\\textbf{proved}" in TEX[:5000]
body_false = "false in the stated" in TEX.lower()
v.record(
    "OP-P92-1 resolution wording is consistent",
    not (abstract_proved and body_false),
    "abstract says proved; body says false in the stated form",
    "single resolution",
    "Expected fail: the abstract contradicts the final resolution section.",
)

preserves_exactly = "preserves $J_{\\rm CKM}$\n  \\emph{exactly}" in TEX
uniform_shifts = "A uniform Peirce scalar is $G_2$-equivariant\nbut shifts $J$ uniformly" in TEX
v.record(
    "equivariant correction preservation claim is consistent",
    not (preserves_exactly and uniform_shifts),
    "abstract says any equivariant correction preserves J exactly; body says a uniform equivariant scalar shifts J",
    "one theorem statement",
    "Expected fail: the body corrects the stronger abstract theorem.",
)

v.record(
    "G2 action treatment of Peirce blocks is consistent",
    not ("Peirce-block-preserving" in TEX and "mixes the Peirce blocks" in TEX),
    "paper says the action is Peirce-block-preserving and later says it mixes Peirce blocks",
    "single Peirce-action model",
    "Expected fail: the uniqueness proof for uniform scaling relies on a block-mixing statement that conflicts with the earlier definition/proof text.",
)

sys.exit(v.summary())
