#!/usr/bin/env python3
"""
verify_P077.py -- Addendum 77: structural seesaw-scale derivation.

This verifier checks the Candidate I formula E_R = E_Pl - 12 + MU*pi/6
and the P77 proof/status claims. The numerical formula is largely
reproducible, but several proof statements are stronger than what is
established in the paper itself.
"""

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("P077 -- Structural Derivation of the Seesaw Scale")

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

PI = math.pi
M_E_MEV = 0.51100
M_PL_GEV = 1.22090e19
E_PL_CANON = 68.096
E_R_OBS = 56.502
SIGMA_E_FROM_TABLE = 0.0088
DM31_FRAC_UNCERT = 0.014
E_V_CANON = 19.636
MNU3_OBS_MEV = 49.5
MNU3_SIGMA_MEV = 0.35

MU0 = 4 * PI**3 + PI**2 + PI
MU1 = 16 * PI**3 / 5 + 3 * PI**2 / 4 + 2 * PI / 3
MU = MU1 / MU0


def spectral_from_gev(mass_gev: float) -> float:
    return PI + math.log((mass_gev * 1000) / M_E_MEV) / MU


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


v.check("mu0 = 4*pi^3 + pi^2 + pi", MU0, 137.036304, rel=5e-9)
v.check("mu1 continuous moment", MU1, 108.716684, rel=5e-9)
v.check("MU = mu1/mu0", MU, 0.793338, rel=1e-5)
v.check(
    "E_Pl from CODATA-style Planck mass and exact MU",
    spectral_from_gev(M_PL_GEV),
    68.096,
    abs_tol=0.002,
    detail="Expected fail: using the P61 CODATA-style inputs gives about 68.092; P77 inherits the rounded canonical 68.096 anchor.",
)

gap_obs = E_PL_CANON - E_R_OBS
epsilon_obs = 12 - gap_obs
epsilon_i = MU * PI / 6
epsilon_ii = MU / 2
gap_pred = 12 - epsilon_i
e_r_pred = E_PL_CANON - gap_pred
residual_e = e_r_pred - E_R_OBS
sigma_e = DM31_FRAC_UNCERT / (2 * MU)

v.check("canonical observed gap 68.096 - 56.502", gap_obs, 11.594, abs_tol=1e-12)
v.check("epsilon from canonical observed gap", epsilon_obs, 0.406, abs_tol=1e-12)
v.check("G2 chamber angle pi/6", PI / 6, 0.5235988, rel=1e-7)
v.check("Candidate I epsilon = MU*pi/6", epsilon_i, 0.415392, rel=5e-5)
v.check("predicted gap = 12 - MU*pi/6", gap_pred, 11.584608, rel=5e-6)
v.check("predicted E_R", e_r_pred, 56.511, abs_tol=0.001)
v.check("residual E_R(pred)-E_R(obs)", residual_e, 0.009, abs_tol=0.001)
v.check("Delta E uncertainty from 1.4 percent Delta m31", sigma_e, 0.0088, rel=5e-3)
v.check(
    "residual sigma using exact formula",
    residual_e / sigma_e,
    1.02,
    rel=2e-2,
    detail="Expected fail: exact substitution gives about 1.06-1.07 sigma; 1.02 uses rounded residual arithmetic.",
)
v.check("residual sigma rounded proof value", residual_e / SIGMA_E_FROM_TABLE, 1.07, rel=5e-3)
v.record(
    "prediction is strictly within one sigma",
    residual_e <= sigma_e,
    f"residual={residual_e:.6f}, sigma={sigma_e:.6f}",
    "residual <= sigma",
    "Expected fail: the result is close but slightly outside a strict one-sigma band.",
)

v.check("Candidate II epsilon = MU/2", epsilon_ii, 0.3967, rel=5e-4)
v.check("Candidate II as MU*sin(pi/6)", MU * math.sin(PI / 6), epsilon_ii, abs_tol=1e-15)
v.check("Candidate I/II relative gap", 100 * (epsilon_i - epsilon_ii) / epsilon_i, 4.5, rel=5e-3)

e_nu_pred = 2 * E_V_CANON - e_r_pred
mnu3_pred_mev = M_E_MEV * math.exp(MU * (e_nu_pred - PI)) * 1e9
v.check("predicted E_nu3 from reflection", e_nu_pred, -17.239, abs_tol=0.001)
v.check("predicted m_nu3 from exact formula", mnu3_pred_mev, 48.7, rel=5e-3)
v.check(
    "m_nu3 percent residual using exact formula",
    100 * (MNU3_OBS_MEV - mnu3_pred_mev) / MNU3_OBS_MEV,
    1.6,
    rel=1e-1,
    detail="Expected fail: exact formula gives about 1.9%; 1.6% follows from rounded 48.7 meV.",
)
v.check(
    "m_nu3 sigma residual using exact formula",
    (MNU3_OBS_MEV - mnu3_pred_mev) / MNU3_SIGMA_MEV,
    2.3,
    rel=5e-2,
    detail="Expected fail: exact formula gives about 2.7 sigma; 2.3 sigma follows from the rounded 48.7 meV value.",
)

# Formal/proof consistency checks.
v.record(
    "G2 subset F4 is not described as a maximal-rank embedding",
    "$G_2 \\subset F_4$ is a maximal rank embedding" not in TEX,
    "paper calls G2 subset F4 maximal rank",
    "rank(G2)=2, rank(F4)=4",
    "Expected fail: the statement conflicts with the ranks printed in the same proposition.",
)
v.record(
    "G2 root system is not treated as a literal E6 sub-root-system",
    "\\Delta(G_2) \\subset \\Delta(E_6)" not in TEX,
    "paper writes Delta(G2) subset Delta(E6)",
    "folded/projected subsystem",
    "Expected fail: E6 is simply-laced while G2 has long and short roots; a literal root subset needs a proof not supplied by the text.",
)
v.record(
    "one-reflection theorem has no internal no-residual contradiction",
    "no residual in group-element" not in TEX,
    "proof says 12 mod 12 = 0, no residual in group-element terms, then asserts one reflection",
    "single residual mechanism",
    "Expected fail: the proof does not derive one reflection from the preceding group-element computation.",
)
v.record(
    "Coxeter-element calculation produces a reflection",
    "rotation by $2\\pi/3$" not in TEX,
    "proof computes a rotation by 2pi/3, then concludes one reflection",
    "reflection",
    "Expected fail: a Coxeter rotation and a Weyl reflection are different Weyl-group elements.",
)
v.record(
    "spectral-angle conversion is fully proved, not assumed",
    "\\textbf{Assumption}" not in TEX and "sole residual assumption" not in TEX,
    "paper labels theta -> MU theta as Assumption and sole residual assumption",
    "proved theorem",
    "Expected fail: the central conversion factor is explicitly conditional.",
)
v.record(
    "Phase 5b closure wording is conditional throughout",
    "Phase~5b is therefore \\emph{closed at the structural level}" not in TEX,
    "paper says closed at the structural level despite a remaining formal assumption",
    "conditional/open until conversion proof",
    "Expected fail: the result is useful, but the closure claim should stay conditional on proving the spectral-angle conversion.",
)

sys.exit(v.summary())
