#!/usr/bin/env python3
"""
verify_P042.py -- Addendum 42: Weinberg angle from sector fractions.

This verifier checks the sector-fraction Weinberg-angle arithmetic and the
Planck-to-MZ running claims in 42_Addendum_WeinbergAngle.tex.

The fraction algebra is solid: edge/(edge+boundary)=1/(1+pi). The flagged
issues are in the proof/status of the RG closure: the effective running
coefficient is fitted from the desired discrepancy, the displayed "exact"
one-loop coefficient does not evaluate to 0.2--0.3, and direct one-loop
running from the absolute CFP coupling values quoted later does not land at
the claimed MZ value.
"""

from __future__ import annotations

import math
import re
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 output adapter: tolerance logic byte-identical to
    verify_common.Verifier.check; emits the modern corpus line format
    ("  [PASS] {n:>2}. {desc}") with computed/claimed/tolerance values
    kept as indented info lines, and the modern RESULT footer."""

    def __init__(self, name: str):
        self.name = name
        self.results = []
        self._n = 0
        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 = abs(computed - claimed)
            err_detail = f"abs err={err:.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._emit(label, ok, computed, claimed, err_detail, detail)

    def record(self, label, ok, computed="", claimed="", detail=""):
        return self._emit(label, ok, computed, claimed, "", detail)

    def _emit(self, label, ok, computed, claimed, info, ann):
        full_detail = (info + (f"; {ann}" if ann else "")) if info else ann
        self.results.append(CheckResult(label, ok, computed, claimed, full_detail))
        self._n += 1
        desc = f"{label} -- {ann}" if ann else label
        print(f"  [{'PASS' if ok else 'FAIL'}] {self._n:>2}. {desc}")
        if computed != "" or claimed != "":
            print(f"        computed: {computed}")
            print(f"        claimed : {claimed}")
        if info:
            print(f"        {info}")
        return ok

    def summary(self):
        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("P042 -- Weinberg Angle Sector Fractions")

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

PI = math.pi
MU0 = 4 * PI**3 + PI**2 + PI
ALPHA = 1 / MU0
PDG_SW = 0.23122
M_PL = 1.22e19
M_Z = 91.2

FRAC_EDGE = PI / MU0
FRAC_BDY = PI**2 / MU0
FRAC_BULK = 4 * PI**3 / MU0
SW_GEOM = FRAC_EDGE / (FRAC_EDGE + FRAC_BDY)
DELTA_SW = SW_GEOM - PDG_SW
LOG_PL_MZ = math.log(M_PL / M_Z)
C_EFF_REQ = DELTA_SW / ((ALPHA / (2 * PI)) * LOG_PL_MZ)
RUN_RATE = DELTA_SW / LOG_PL_MZ


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


v.check("mu0", MU0, 137.036, rel=3e-6)
v.check("FRAC_edge", FRAC_EDGE, 0.022925, rel=2e-5)
v.check("FRAC_bdy", FRAC_BDY, 0.072022, rel=2e-5)
v.check("FRAC_bulk", FRAC_BULK, 0.90505, rel=5e-6)
v.check("sector fractions sum", FRAC_EDGE + FRAC_BDY + FRAC_BULK, 1.0, rel=1e-12)
v.check("FRAC_edge/FRAC_bdy", FRAC_EDGE / FRAC_BDY, 1 / PI, rel=1e-12)
v.check("Weinberg geometric 1/(1+pi)", SW_GEOM, 0.2415, rel=2e-4)
v.check("Weinberg discrepancy absolute", DELTA_SW, 0.01023, rel=5e-4)
v.check("Weinberg discrepancy percent", pct(SW_GEOM, PDG_SW), 4.4, rel=8e-3)
v.check("inverse CFP assignment", FRAC_BDY / (FRAC_EDGE + FRAC_BDY), 0.759, rel=1e-3)

v.check("ln(M_Pl/M_Z)", LOG_PL_MZ, 39.4, rel=1e-3)
v.check("required C_eff", C_EFF_REQ, 0.224, rel=5e-3)
v.check("required running rate", RUN_RATE, 2.6e-4, rel=5e-3)
v.check("predicted MZ after fitted correction", SW_GEOM - 0.0102, 0.2313, rel=5e-4)

b1 = 41 / 6
b2 = -19 / 6
s2 = PDG_SW
c2 = 1 - s2
paper_coeff = (b1 * c2 - b2 * s2) / (b1 + b2)
v.check(
    "displayed exact one-loop coefficient",
    paper_coeff,
    0.224,
    rel=2e-1,
    detail="Expected fail: the displayed formula evaluates to about 1.63, not order 0.2--0.3.",
)
v.record(
    "RG coefficient is derived independently of the observed discrepancy",
    False,
    "C_eff is defined as Delta(sin^2 theta_W) divided by alpha/(2pi)*log(M_Pl/M_Z)",
    "independent one-loop prediction",
    "Expected proof-audit fail: this step fits the required coefficient, then compares it to a rough SM rate.",
)

# If one takes the later explicit CFP normalization g_k^2=FRAC_k literally
# and runs the two gauge couplings at one loop from M_Pl down to M_Z, the
# result is not the fitted 0.2313. This checks internal consistency, not a
# standard-model global fit.
inv_g_y2_low = 1 / FRAC_EDGE + b1 * LOG_PL_MZ / (8 * PI**2)
inv_g_w2_low = 1 / FRAC_BDY + b2 * LOG_PL_MZ / (8 * PI**2)
g_y2_low = 1 / inv_g_y2_low
g_w2_low = 1 / inv_g_w2_low
sw_direct_run = g_y2_low / (g_y2_low + g_w2_low)
v.check(
    "direct 1-loop run from explicit CFP g_k^2=FRAC_k",
    sw_direct_run,
    0.2313,
    rel=5e-3,
    detail="Expected fail: literal one-loop running of the quoted absolute CFP couplings gives about 0.207.",
)
v.record(
    "absolute CFP couplings share the SM normalization",
    False,
    computed=f"gY={math.sqrt(FRAC_EDGE):.3f}, gW={math.sqrt(FRAC_BDY):.3f}",
    claimed="directly comparable SM gauge couplings",
    detail="Expected status fail: the paper uses the fraction normalization for ratios, but the absolute values need a normalization map before RG use.",
)

v.check("gY^2/gW^2 from CFP", FRAC_EDGE / FRAC_BDY, 1 / PI, rel=1e-12)
v.check("g_s^2/g_W^2 from CFP", FRAC_BULK / FRAC_BDY, 4 * PI, rel=1e-12)
v.check("gY from explicit CFP", math.sqrt(FRAC_EDGE), 0.151, rel=3e-3)
v.check("gW from explicit CFP", math.sqrt(FRAC_BDY), 0.268, rel=3e-3)
v.check("gs from explicit CFP", math.sqrt(FRAC_BULK), 0.951, rel=5e-4)

open_items = re.findall(r"Identify\s+\$\\Lambda_\{\\mathrm\{geom\}\}\$\s+precisely", TEX)
v.record(
    "open-item list has no duplicate Lambda_geom entry",
    len(open_items) <= 1,
    computed=f"duplicate count={len(open_items)}",
    claimed="one Lambda_geom open item",
    detail="Expected TeX-audit fail: the same open item appears twice.",
)
v.record(
    "CFP is proven unconditionally in P42",
    "must be stated as a postulate" not in TEX,
    "paper explicitly says CFP is a postulate pending a Noether-charge proof",
    "unconditional proof",
    "Expected status fail: the Weinberg result is conditional on CFP.",
)

sys.exit(v.summary())
