#!/usr/bin/env python3
"""
verify_P081.py -- Addendum 81: Wolfenstein A NLO correction.

This verifier checks the numerical A_NLO chain and the Jordan-loop algebra in
81_Addendum_WolfensteinANLO.tex.  The headline numerical formula
A0*(1 - 4 lambda^2/5) does land near the PDG Wolfenstein A value.  The flagged
issues are derivational: with Hermitian off-diagonal conventions the displayed
two-step Jordan loop has the opposite sign for a simple imaginary test case;
the paper's own correction formula with a 1/4 loop factor gives -lambda^2/5,
not -4lambda^2/5; the lambda^4 estimate is off by a factor of ten; and the
paper declares N=5 and Sigma=4lambda^2 proved while listing rigorous versions
of both as open problems.
"""

from __future__ import annotations

import math
import sys
from pathlib import Path

import numpy as np

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


class ModernVerifier(Verifier):
    """Local adapter: modern check-line output format. Tolerance logic is
    inherited unchanged from verify_common.Verifier; only printing differs.
    Computed/claimed values stay as indented info lines."""

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

    def record(self, label, ok, computed="", claimed="", detail=""):
        self.results.append(CheckResult(label, ok, computed, claimed, detail))
        status = "PASS" if ok else "FAIL"
        desc = f"{label} -- {detail}" if detail else label
        print(f"  [{status}] {len(self.results):>2}. {desc}")
        if computed != "" or claimed != "":
            print(f"          computed: {computed}")
            print(f"          claimed : {claimed}")
        return ok

    def summary(self) -> int:
        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("P081 -- Wolfenstein A NLO")

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

PI = math.pi
LAM = math.sin(PI / 14.0)
LAM2 = LAM**2
A_OBS = 0.823
A_SIGMA = 0.015


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


def offdiag(i: int, j: int, x: complex) -> np.ndarray:
    m = np.zeros((3, 3), dtype=complex)
    m[i, j] = x
    m[j, i] = np.conj(x)
    return m


def jordan(a: np.ndarray, b: np.ndarray) -> np.ndarray:
    return 0.5 * (a @ b + b @ a)


def coeff(a: np.ndarray, basis: np.ndarray) -> complex:
    return np.vdot(basis, a) / np.vdot(basis, basis)


A0 = math.cos(PI / 14.0) ** 2 * math.cos(2.0 * PI / 14.0)
corr = 4.0 * LAM2 / 5.0
A1 = A0 * (1.0 - corr)
proof_corr = LAM2 / 5.0
A1_from_written_loop_formula = A0 * (1.0 - proof_corr)

v.check("lambda=sin(pi/14)", LAM, 0.22252, rel=5e-5)
v.check("lambda^2", LAM2, 0.04952, rel=1e-4)
v.check("cos(pi/14)", math.cos(PI / 14.0), 0.97493, rel=3e-6)
v.check("cos^2(pi/14)", math.cos(PI / 14.0) ** 2, 0.95049, rel=6e-6)
v.check("cos(2pi/14)", math.cos(2.0 * PI / 14.0), 0.90097, rel=2e-6)
v.check("A0", A0, 0.85630, rel=7e-5)
v.check("4lambda^2/5", corr, 0.039616, rel=1e-4)
v.check("1-4lambda^2/5", 1.0 - corr, 0.960384, rel=4e-6)
v.check("A1 headline formula", A1, 0.82238, rel=7e-5)
v.check("A1 residual absolute", abs(A1 - A_OBS), 0.00062, rel=1e-1)
v.check("A1 residual percent", abs(pct(A1, A_OBS)), 0.075, rel=1e-1)
v.check("A1 residual in sigma", abs(A1 - A_OBS) / A_SIGMA, 0.04, rel=7e-2)
v.check("Vcb from A1 lambda^2", A1 * LAM2, 0.04073, rel=2e-4)
v.check("Vcb residual percent", abs(pct(A1 * LAM2, 0.04110)), 0.9, rel=1e-1)

e12_i = offdiag(0, 1, 1j)
e23_1 = offdiag(1, 2, 1.0)
e13_i = offdiag(0, 2, 1j)
step1 = jordan(e23_1, e12_i)
loop = jordan(step1, e12_i)
v.check("Jordan first step E23(1) o E12(i) coefficient", coeff(step1, e13_i).real, 0.5, rel=1e-12)
v.check(
    "Jordan loop eigenvalue on E23 for imaginary unit",
    coeff(loop, e23_1).real,
    -0.25,
    rel=1e-12,
    detail="Expected fail: Hermitian matrix multiplication gives +1/4; the paper's -1/4 comes from dropping the conjugation/sign in the second Peirce product.",
)

v.check("sector sum Sigma", 4.0 * LAM2, 4.0 * 0.04952, rel=1e-4)
v.check(
    "written loop-correction formula gives -4lambda^2/5",
    -((1.0 / 4.0) * (4.0 * LAM2)) / 5.0,
    -4.0 * LAM2 / 5.0,
    rel=1e-12,
    detail="Expected fail: -(1/4 * 4lambda^2)/5 = -lambda^2/5, not -4lambda^2/5.",
)
v.check(
    "A1 from written loop formula",
    A1_from_written_loop_formula,
    0.82238,
    rel=7e-5,
    detail="Expected fail: keeping the displayed 1/4 loop factor gives A≈0.84788.",
)
v.check(
    "8lambda^4/5 estimate",
    8.0 * LAM2**2 / 5.0,
    3.9e-4,
    rel=5e-2,
    detail="Expected fail: 8lambda^4/5 is about 0.00392, not 0.00039.",
)

v.record(
    "N=5 is fully rigorously derived here",
    "OP-81-2" not in TEX,
    computed="paper lists rigorous N=5 derivation from the G2 root system as OP-81-2",
    claimed="N=5 proved from G2/SU(3) geometry",
    detail="Expected status fail.",
)
v.record(
    "Sigma=4lambda^2 is derived from first principles here",
    "OP-81-3" not in TEX,
    computed="paper lists first-principles sector-coupling derivation from the explicit G2 trilinear form as OP-81-3",
    claimed="Sigma=4lambda^2 proved",
    detail="Expected status fail.",
)
v.record(
    "Phase 5f is unconditionally closed",
    False,
    computed="headline numeric formula matches A, but the loop sign/coefficient and N/Sigma proof status remain unresolved",
    claimed="Phase 5f is closed",
    detail="Expected status fail.",
)

sys.exit(v.summary())
