#!/usr/bin/env python3
"""
verify_P053.py -- Addendum 53: Type-I seesaw and Cabibbo-step neutrino ratio.

This verifier checks the seesaw-scale estimates, Cabibbo-step Yukawa ratio,
anchored neutrino spectrum, and PMNS-invariance claims in 53_Addendum_Seesaw.tex.
The headline r_TOE arithmetic is reproducible.  The flagged issues are narrower:
a Planck-option neutrino-mass unit error, a PMNS-invariance proof that is only
valid for real orthogonal mixing despite saying unitary, a TBM angle typo, and
a non-universal-M_R correction estimate with the wrong sign under the simple
model stated in the text.
"""

from __future__ import annotations

import math
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from verify_common import CheckResult, Verifier


class _ModernVerifier(Verifier):
    """Local adapter: identical tolerance logic, modern output format."""

    def __init__(self, name: str):
        self.name = name
        self.results = []
        print(name)

    def record(self, label, ok, computed="", claimed="", detail=""):
        self.results.append(CheckResult(label, ok, computed, claimed, detail))
        n = len(self.results)
        desc, info = label, detail
        i = detail.find("Expected")
        if i >= 0:
            desc = f"{label} -- {detail[i:]}"
            info = detail[:i].rstrip().rstrip(";")
        print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {desc}")
        if computed != "" or claimed != "":
            print(f"        computed: {computed}")
            print(f"        claimed : {claimed}")
        if info:
            print(f"        {info}")
        return bool(ok)

    def summary(self) -> int:
        passed = sum(bool(r.ok) for r in self.results)
        failed = len(self.results) - passed
        print(f"\n{'='*60}\nRESULT: {passed} PASS / {failed} FAIL")
        return 1 if failed else 0


v = _ModernVerifier("P053 -- Type-I Seesaw Cabibbo-Step Ratio")

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

PI = math.pi
MU0 = 4 * PI**3 + PI**2 + PI
MU1 = 16 * PI**3 / 5 + 3 * PI**2 / 4 + 2 * PI / 3
MU = MU1 / MU0
ME_MEV = 0.511
ME_GEV = 0.511e-3
MZ = 91.188
V_EW_CAND = math.e * MZ
MNU3_GEV = 49.5e-3 * 1e-9


def energy(mass_gev: float) -> float:
    return PI + math.log(mass_gev / ME_GEV) / MU


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


v.check("mu0", MU0, 137.036, rel=3e-6)
v.check("mu1", MU1, 108.717, rel=5e-6)
v.check("MU", MU, 0.79334, rel=5e-6)
v.check("bulk mass option in MeV", ME_MEV * math.exp(MU * (4 * PI**3 - PI)), 2.3e41, rel=2e-2)
mpl_toe = ME_GEV * math.exp(MU * MU1 / PI)
v.check("TOE Planck mass option", mpl_toe, 4.28e8, rel=5e-3)
planck_option_mnu_gev = V_EW_CAND**2 / mpl_toe
v.check(
    "Planck-option seesaw neutrino mass",
    planck_option_mnu_gev,
    1e-1,
    rel=2e-1,
    detail="Expected fail: v^2/M_Pl_TOE is about 1.4e-4 GeV (0.14 MeV), not 10^-1 GeV.",
)

mr_phenom = V_EW_CAND**2 / MNU3_GEV
v.check("phenomenological M_R from e*MZ and 49.5 meV", mr_phenom, 1.24e15, rel=2e-3)
v.check("E_R from phenomenological M_R", energy(mr_phenom), 56.502, rel=3e-5)

s1 = math.sin(PI / 14)
s2 = math.sin(2 * PI / 14)
s7 = math.sin(7 * PI / 14)
r_toe = (s2**4 - s1**4) / (1 - s1**4)
v.check("Cabibbo y1", s1, 0.22252, rel=5e-5)
v.check("Cabibbo y2", s2, 0.43388, rel=1e-5)
v.check("Cabibbo y3", s7, 1.0, rel=1e-12)
v.check("sin^4(pi/14)", s1**4, 0.002455, rel=2e-3)
v.check("sin^4(2pi/14)", s2**4, 0.035477, rel=2e-3)
v.check("r_TOE", r_toe, 0.03307, rel=3e-5)
v.check("r residual vs PDG", pct(r_toe, 0.03070), 7.7, rel=5e-3)
v.check("Delta m21 anchored to 2.45e-3", r_toe * 2.45e-3, 8.09e-5, rel=2e-3)

m1 = 49.5 * s1**2
m2 = 49.5 * s2**2
m3 = 49.5
v.check("light mnu1 anchored", m1, 2.45, rel=3e-3)
v.check("light mnu2 anchored", m2, 9.32, rel=5e-4)
v.check("light mnu3 anchor", m3, 49.5, rel=1e-12)
v.check("light neutrino sum", m1 + m2 + m3, 61.3, rel=8e-4)

v.record(
    "PMNS invariance proof is valid for general unitary PMNS as written",
    False,
    computed="lemma states U unitary but proof uses U diag(y^2) U^T and says U is orthogonal",
    claimed="independent of PMNS angles for unitary U",
    detail="Expected proof-audit fail: for complex PMNS one should use the Hermitian YY† spectrum or a Takagi argument; the written proof only covers real orthogonal U.",
)
v.record(
    "TBM comparison row has theta23 correctly stated",
    "theta_{13}=\\theta_{23}=0" not in TEX,
    computed="table says TBM theta13=theta23=0",
    claimed="TBM theta23 is maximal (45 degrees)",
    detail="Expected table fail: theta13=0 for TBM, but theta23 is not 0.",
)

v.check("best old candidate 1/(4pi^2)", 1 / (4 * PI**2), 0.02533, rel=2e-4)
v.check("old candidate residual", pct(1 / (4 * PI**2), 0.03070), -17.5, rel=1e-3)
v.check("improvement factor", abs(-17.5) / abs(pct(r_toe, 0.03070)), 2.3, rel=2e-2)
alt_y3 = math.sin(6 * PI / 14)
alt_r = (s2**4 - s1**4) / (alt_y3**4 - s1**4)
v.check("alternative y3=sin(6pi/14) r", alt_r, 0.0366, rel=5e-4)
v.check("alternative y3 residual", pct(alt_r, 0.03070), 19.0, rel=2e-2)

# Simple interpretation of the text's non-universal-M_R sentence:
# hold M1=M3 and vary q=M2/M3 so r reaches the PDG target.
q_required = math.sqrt(s2**4 / (0.03070 * (1 - s1**4) + s1**4))
v.check(
    "non-universal M_R2/M_R3 required for PDG r",
    q_required,
    0.98,
    rel=2e-2,
    detail="Expected fail: the simple M1=M3 model requires M_R2/M_R3≈1.035, not 0.98.",
)

v.record(
    "Cabibbo-step Yukawa derivation is explicitly open",
    "Cabibbo-step Dirac Ansatz" in TEX and "Open" in TEX,
    computed="open status present",
    claimed="conditional ansatz",
)

sys.exit(v.summary())
