"""v159 -- PyR@TE cross-check: the carrier field content reproduces the SM
one-loop gauge beta coefficients, and b1 = 41/10 is fixed three independent ways.

This is an F_transfer consistency check: the gauge running that carries the
TFPT boundary data down to observables uses the one-loop coefficients
(b1, b2, b3). TFPT does not import them -- the U(1) coefficient is the carrier
hypercharge index 10 b1 = g_car 2^{g_car-2}+1 = 41 (tfpt_2 Gate 1). Here we
re-derive ALL THREE coefficients from the field content with the textbook
one-loop formula, and confirm they equal the values the third-party tool
PyR@TE 3 writes from the same content.

  [I] 1. THREE INDEPENDENT PATHS TO b1.  (a) carrier algebra:
         10 b1 = g_car 2^{g_car-2}+1 = 41 (tfpt_constants.b1, from g_car alone);
         (b) SM/QFT: b1 = (2/3) sum_f t1(f) + (1/3) sum_s t1(s) over the carrier
         field content, GUT normalized t1 = (3/5) Y^2 x mult; (c) PyR@TE 3
         (external tool) writes beta_g1 = (41/10) g1^3. All three give 41/10.
  [I] 2. THE FULL ONE-LOOP VECTOR.  The same textbook formula on the carrier
         content gives (b1, b2, b3) = (41/10, -19/6, -7) -- exactly what PyR@TE
         writes (verification/pyrate/sm_gauge_betas.txt), and the standard SM.
  [I] 3. THE M = 41 DECOMPOSITION.  10 b1 splits as 40 (fermion U(1) index,
         sum_{f,j} L_{f,j}) + 1 (one Higgs doublet, N_Phi) = 41 -- exactly the
         "EM budget M = sum L + N_Phi = 41" of tfpt_2 Gate 1.
  [P] 4. F_transfer INPUT CONFIRMED.  The gauge-running inputs of the transfer
         functor are not free knobs: they follow from the carrier content, and
         an independent RGE generator (PyR@TE 3, arXiv:2007.12700) reproduces
         them verbatim at one and two loops. (The 2-loop matrix is recorded in
         the evidence file; only the 1-loop vector is load-bearing here.)

Scope: this validates the gauge sector of F_transfer. PyR@TE is the right tool
for the transfer/RGE gates (gauge running, and -- with a seesaw model -- the
neutrino-Yukawa running behind eta_B); it is NOT a tool for premise (A) (the
boundary holomorphic fixed point), which is a 2d boundary-CFT question.
External evidence regenerated by verification/pyrate/reproduce.sh.
"""
import os

import sympy as sp

from tfpt_constants import check, summary, reset, g_car, N_fam, b1 as b1_const

# carrier / SM field content (hypercharges in the Q = T3 + Y convention, as in
# PyR@TE's models/SM.model). Each entry: (name, Y, dimSU2, dimSU3, n_gen, kind).
FIELDS = [
    ("Q",  sp.Rational(1, 6), 2, 3, 3, "weyl"),
    ("L",  sp.Rational(-1, 2), 2, 1, 3, "weyl"),
    ("uR", sp.Rational(2, 3), 1, 3, 3, "weyl"),
    ("dR", sp.Rational(-1, 3), 1, 3, 3, "weyl"),
    ("eR", sp.Integer(-1), 1, 1, 3, "weyl"),
    ("H",  sp.Rational(1, 2), 2, 1, 1, "cscalar"),  # one complex Higgs doublet
]
C2 = {"SU2": sp.Integer(2), "SU3": sp.Integer(3)}   # adjoint Casimirs
PRE = {"weyl": sp.Rational(2, 3), "cscalar": sp.Rational(1, 3)}  # 1-loop matter prefactors


def _u1_index(f):
    _, Y, d2, d3, ng, _ = f
    return sp.Rational(3, 5) * Y**2 * d2 * d3 * ng        # GUT-normalized t1

def _su2_index(f):
    _, _, d2, d3, ng, _ = f
    return sp.Rational(1, 2) * d3 * ng if d2 == 2 else sp.Integer(0)

def _su3_index(f):
    _, _, d2, d3, ng, _ = f
    return sp.Rational(1, 2) * d2 * ng if d3 == 3 else sp.Integer(0)


def run():
    reset()
    print("v159 PyR@TE gauge cross-check (carrier content -> SM 1-loop b_i)")

    # ---- one-loop coefficients from the carrier field content ---------------
    b1 = sum(PRE[f[5]] * _u1_index(f) for f in FIELDS)
    b2 = -sp.Rational(11, 3) * C2["SU2"] + sum(PRE[f[5]] * _su2_index(f) for f in FIELDS)
    b3 = -sp.Rational(11, 3) * C2["SU3"] + sum(PRE[f[5]] * _su3_index(f) for f in FIELDS)

    # 1. three independent paths to b1
    carrier_b1 = sp.Rational(g_car * 2**(g_car - 2) + 1, 10)   # (5*8+1)/10 = 41/10
    check("THREE PATHS TO b1 = 41/10: carrier algebra "
          "10 b1 = g_car 2^{g_car-2}+1 = 41; SM Sum (3/5)Y^2 field index; "
          "PyR@TE beta_g1 = (41/10) g1^3 -- all agree",
          b1 == sp.Rational(41, 10) and carrier_b1 == sp.Rational(41, 10)
          and abs(float(b1_const) - 41/10) < 1e-12, exact=False)

    # 2. the full one-loop vector matches PyR@TE / the standard SM
    check("ONE-LOOP VECTOR (b1,b2,b3) = (41/10, -19/6, -7) from the carrier "
          "content -- identical to PyR@TE's beta_g{1,2,3} and the standard SM",
          (b1, b2, b3) == (sp.Rational(41, 10), sp.Rational(-19, 6), sp.Integer(-7)),
          exact=True)

    # 3. the M = 41 decomposition (fermion index 40 + one Higgs)
    ferm_index = sum(PRE["weyl"] * _u1_index(f) for f in FIELDS if f[5] == "weyl")
    scal_index = sum(PRE["cscalar"] * _u1_index(f) for f in FIELDS if f[5] == "cscalar")
    M_ferm = sp.Integer(10) * ferm_index      # 40
    M_scal = sp.Integer(10) * scal_index      # 1
    check("M = 41 DECOMPOSITION: 10 b1 = 40 (fermion U(1) index = Sum L_{f,j}) "
          "+ 1 (one Higgs doublet N_Phi) = 41 -- exactly tfpt_2 Gate 1",
          M_ferm == 40 and M_scal == 1 and (M_ferm + M_scal) == 41, exact=True)

    # internal consistency: N_fam = 3 (used as a sanity tie to the field content)
    check("CONTENT SANITY: 3 fermion generations (N_fam = 3) feed the index; "
          "the three b_i are exactly rational (no fit)",
          N_fam == 3 and all(isinstance(x, sp.Rational) or x.is_integer
                              for x in (b1, b2, b3)), exact=True)

    # 4. external evidence is present and pins the same 1-loop values
    here = os.path.dirname(os.path.abspath(__file__))
    evidence = os.path.join(here, "pyrate", "sm_gauge_betas.txt")
    have_ev = os.path.isfile(evidence)
    ev_ok = have_ev and "(41/10)*g1**3" in open(evidence).read() \
        and "-19/6*g2**3" in open(evidence).read() \
        and "-7*g3**3" in open(evidence).read()
    check("EXTERNAL EVIDENCE: verification/pyrate/sm_gauge_betas.txt records "
          "PyR@TE 3's beta_g1=(41/10)g1^3, beta_g2=-19/6 g2^3, beta_g3=-7 g3^3 "
          "(reproduce.sh regenerates it) -- F_transfer gauge inputs confirmed",
          ev_ok, exact=False)

    return summary("v159 PyR@TE gauge cross-check")


if __name__ == "__main__":
    raise SystemExit(1 if run() else 0)
