#!/usr/bin/env python3
"""
verify_P092.py -- Addendum 92: NLO correction to delta_CKM and Jarlskog.

This verifier checks the required eta inversion, phase-only obstruction,
single-loop obstruction, paired-correction algebra, and the final numerical
tables in 92_Addendum_NLO_dCKM.tex.

The main structural logic is partly coherent: the central eta target is about
0.3749, a phase-only correction is impossible, natural single-loop corrections
have the wrong sign, and the formal paired correction cancels O(lambda^2) terms.
The flagged issues are internal consistency problems: the abstract keeps the
stale 0.384/11.8% eta target; the exact Phi formula still gives 0.743745, not
0.7429; and the final paired-correction table treats 8 lambda^2/5 as 0.792%
instead of 7.92%, which makes the displayed Phi/eta/J rows inconsistent with
the theorem.
"""

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):
    """Output adapter: modern check-line format. Tolerance logic is
    inherited unchanged from verify_common.Verifier; only printing and
    the footer differ."""

    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)
        expected = (not ok) and ("Expected" in str(detail))
        desc = f"{label} -- {detail}" if expected else label
        print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {desc}")
        if computed != "" or claimed != "":
            print(f"       computed: {computed}")
            print(f"       claimed : {claimed}")
        if detail and not expected:
            print(f"       {detail}")
        return ok

    def summary(self):
        passed = sum(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("P092 -- NLO dCKM and Jarlskog")

PI = math.pi
LAM = math.sin(PI / 14)
LAM2 = LAM**2
LAM4 = LAM2**2
LAM6 = LAM**6
SQRT_1ML2 = math.sqrt(1 - LAM2)
A_LO = math.cos(PI / 14) ** 2 * math.cos(2 * PI / 14)
F_A = 1 - 4 * LAM2 / 5
A_NLO = A_LO * F_A
DELTA = 31 * PI / 84
SIN_DELTA = math.sin(DELTA)
COS_DELTA = math.cos(DELTA)
PHI_EXACT = math.cos(PI / 14) * math.cos(2 * PI / 14) * math.cos(5 * PI / 28)
PHI_STALE = 0.7429
ETA_EXACT = 0.5 * PHI_EXACT * SIN_DELTA
RHO_EXACT = 0.5 * PHI_EXACT * COS_DELTA
ETA_STALE = 0.3439
J_PDG = 3.08e-5
J_SIGMA = 0.15e-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^6", LAM6, 1.2148e-4, rel=8e-4)
v.check("sqrt(1-lambda^2)", SQRT_1ML2, 0.97492, rel=1e-5)
v.check("A_LO exact formula", A_LO, 0.8563, rel=1e-4)
v.check("A_NLO exact formula", A_NLO, 0.8224, rel=5e-5)
v.check("delta_CKM degrees", math.degrees(DELTA), 66.43, rel=3e-5)
v.check("sin(delta_CKM)", SIN_DELTA, 0.9162, rel=5e-4)

v.check(
    "Phi exact formula",
    PHI_EXACT,
    0.7429,
    rel=5e-4,
    detail="Expected fail: the printed exact trigonometric formula gives about 0.743745.",
)
v.check(
    "rho_bar from exact Phi",
    RHO_EXACT,
    0.1484,
    rel=5e-4,
    detail="Expected fail: exact Phi gives about 0.148709.",
)
v.check(
    "eta_LO from exact Phi",
    ETA_EXACT,
    0.3439,
    rel=5e-4,
    detail="Expected fail: exact Phi gives about 0.340844.",
)

j_lo_exact = A_LO**2 * LAM6 * ETA_EXACT
j_nlo_a_exact = A_NLO**2 * LAM6 * ETA_EXACT
j_lo_rounded = 0.8563**2 * 1.2148e-4 * 0.3439
j_nlo_a_rounded = 0.8224**2 * 1.2148e-4 * 0.3439
v.check("J_LO rounded inherited path", j_lo_rounded, 3.064e-5, rel=5e-4)
v.check("J_NLO A-only rounded path", j_nlo_a_rounded, 2.826e-5, rel=5e-4)
v.check(
    "J_LO from exact stated formulas",
    j_lo_exact,
    3.064e-5,
    rel=5e-4,
    detail="Expected fail: exact Phi-derived eta gives about 3.035e-5.",
)
v.check(
    "J_NLO A-only from exact stated formulas",
    j_nlo_a_exact,
    2.826e-5,
    rel=5e-4,
    detail="Expected fail: exact Phi-derived eta gives about 2.799e-5.",
)

# Required eta inversion.
eta_req_rounded = J_PDG / (0.8224**2 * 1.2148e-4)
eta_req_exact = J_PDG / (A_NLO**2 * LAM6)
v.check(
    "abstract required eta 0.3844",
    eta_req_rounded,
    0.3844,
    rel=5e-3,
    detail="Expected fail: the inversion gives about 0.37487; the proof later corrects the abstract value.",
)
v.check("proof required eta central", eta_req_rounded, 0.37487, rel=2e-5)
v.check("exact-formula required eta central", eta_req_exact, 0.3749, rel=5e-4)
v.check(
    "abstract required eta fractional shift +11.8 percent",
    residual_pct(eta_req_rounded, ETA_STALE),
    11.8,
    rel=5e-2,
    detail="Expected fail: relative to eta_LO=0.3439, the corrected central shift is about +9.0%.",
)
v.check("corrected required eta shift vs stale eta", residual_pct(eta_req_rounded, ETA_STALE), 9.0, rel=2e-2)
v.check("required eta shift in lambda^2 units", residual_pct(eta_req_rounded, ETA_STALE) / 100 / LAM2, 1.82, rel=2e-2)

# Phase-only obstruction and Phi lower bound.
sin_required_stale_phi = 2 * 0.3749 / PHI_STALE
sin_required_exact_phi = 2 * eta_req_exact / PHI_EXACT
v.check("phase-only required sine using paper values", sin_required_stale_phi, 1.0093, rel=2e-4)
v.record("phase-only correction is impossible", sin_required_exact_phi > 1, f"sin_required={sin_required_exact_phi:.6f}", ">1")
phi_lower = 2 * eta_req_rounded
v.check("Phi lower bound paper arithmetic", 2 * 0.3749, 0.7498, rel=1e-12)
v.check("Phi lower-bound fractional increase with stale Phi", residual_pct(0.7498, PHI_STALE), 0.93, rel=5e-2)

# Single-loop obstruction.
for orbit_dim, claimed_factor, claimed_pct in [
    (5, 1 - 0.00990, -0.99),
    (6, 1 - 0.00825, -0.83),
    (7, 1 - 0.00707, -0.71),
    (14, 1 - 0.00354, -0.35),
]:
    factor = 1 - LAM2 / orbit_dim
    v.check(f"single-loop factor N={orbit_dim}", factor, claimed_factor, rel=8e-5)
    v.check(f"single-loop percent N={orbit_dim}", 100 * (factor - 1), claimed_pct, rel=2e-2)
v.record("all natural single-loop corrections lower Phi", all(1 - LAM2 / n < 1 for n in [5, 6, 7, 14]), "negative shifts", "wrong sign")

# Paired correction theorem.
paired_phi_factor = 1 + 8 * LAM2 / 5
paired_q_factor = F_A**2 * paired_phi_factor
first_omitted = 48 * LAM4 / 25
v.check("paired Phi factor 1 + 8 lambda^2/5", paired_phi_factor, 1.0792, rel=3e-5)
v.check(
    "paired Phi correction percent in final table",
    100 * (paired_phi_factor - 1),
    0.792,
    rel=5e-2,
    detail="Expected fail: 8 lambda^2/5 is about +7.92%, not +0.792%.",
)
v.check("paired Q exact factor", paired_q_factor, 1 - first_omitted, rel=2e-3)
v.check("48 lambda^4 / 25", first_omitted, 4.70e-3, rel=3e-3)
v.record("paired correction cancels O(lambda^2) terms", abs((paired_q_factor - 1) + first_omitted) < 2e-4, f"factor={paired_q_factor:.9f}", "1 + O(lambda^4)")

v.check("N_eff with sign-reversed L=+1/4", (1 / 4) / (2 / 5), 5 / 8, rel=1e-12)
v.check("N_eff with universal L=-1/4", (-1 / 4) / (2 / 5), -5 / 8, rel=1e-12)
v.record("no positive integer single-loop orbit dimension gives paired correction", 2 / 5 not in {1 / (4 * n) for n in range(1, 20)}, "L/N=2/5 required", "no integer N")

# Final tables.
phi_paired_stale = PHI_STALE * paired_phi_factor
eta_paired_stale = ETA_STALE * paired_phi_factor
j_paired_stale = 0.8224**2 * 1.2148e-4 * eta_paired_stale
v.check(
    "paired table Phi NLO value",
    phi_paired_stale,
    0.7488,
    rel=5e-4,
    detail="Expected fail: applying +8 lambda^2/5 to 0.7429 gives about 0.8018; 0.7488 uses +0.792%.",
)
v.check(
    "paired table eta NLO value",
    eta_paired_stale,
    0.3466,
    rel=5e-4,
    detail="Expected fail: applying +8 lambda^2/5 to 0.3439 gives about 0.3711.",
)
v.check(
    "paired table J NLO value",
    j_paired_stale,
    3.064e-5,
    rel=5e-4,
    detail="Expected fail: exact paired table path gives about 3.049e-5 because the O(lambda^4) residual remains.",
)

j_required_eta = 0.8224**2 * 1.2148e-4 * 0.3749
v.check("required-eta row J", j_required_eta, 3.080e-5, rel=2e-4)
v.check(
    "conjectured NLO row with eta=0.3749 gives J=3.064e-5",
    j_required_eta,
    3.064e-5,
    rel=5e-4,
    detail="Expected fail: if eta=0.3749 and A=0.8224, the product gives PDG-central J, not the LO value.",
)
v.record(
    "conjectured NLO table uses one eta value consistently",
    abs(eta_paired_stale - 0.3749) < 1e-4,
    f"paired eta from theorem={eta_paired_stale:.6f}, table eta=0.3749",
    "same eta",
    "Expected fail: the theorem's paired factor and the table's required-eta row are different scenarios.",
)

sys.exit(v.summary())
