#!/usr/bin/env python3
"""Precompute mpmath high-precision O3 vectors for electrical.rf.antenna_length.

Independent of Node/V8 binary64 and of the IUT. L = (c/f)·k·frac with
c = 299792458 m/s (SI exact). Uses mpmath at 80 dps; does not pin a
gmpy2 backend.

Re-run: python3 scripts/lib/cvp/oracles/generate-antenna-length-o3.py
Public copies: /developers/cvp/reproduce/generate-antenna-length-o3.py
and antenna-length-o3-tables.json
"""
from __future__ import annotations

import json
import math
import shutil
from pathlib import Path

import mpmath as mp

DPS = 80
GENERATOR_ID = "antenna-length-mpmath-o3"
GENERATOR_VERSION = "1.0.0"
SEED = "20260911.antenna-o3"
C0 = mp.mpf(299792458)


def f64(x: mp.mpf) -> float:
    return float(x)


def frac_for(mode: str) -> mp.mpf:
    if mode in ("quarter",):
        return mp.mpf("0.25")
    if mode in ("wavelength", "full"):
        return mp.mpf(1)
    return mp.mpf("0.5")


def row(vid: str, mode: str, f_hz: float, k: float, *, kind: str) -> dict:
    freq = mp.mpf(f_hz)
    vf = mp.mpf(k)
    lam = C0 / freq
    scale = lam * vf
    length = scale * frac_for(mode)
    mode_out = "wavelength" if mode == "full" else mode
    return {
        "id": vid,
        "kind": kind,
        "inputs": {"mode": mode, "f_Hz": f_hz, "length_factor": k},
        "mode_out": mode_out,
        "L_m_f64": f64(length),
        "y_f64": f64(length),
        "L_m_decimal": mp.nstr(length, 40, strip_zeros=False),
        "lambda_free_space_m_f64": f64(lam),
        "lambda_free_space_m_decimal": mp.nstr(lam, 40, strip_zeros=False),
    }


def vectors() -> list[dict]:
    return [
        row("o3-half-c", "half", 299792458, 1.0, kind="canonical-half"),
        row("o3-quarter-c", "quarter", 299792458, 1.0, kind="canonical-quarter"),
        row("o3-wavelength-c", "wavelength", 299792458, 1.0, kind="canonical-wavelength"),
        row("o3-full-alias", "full", 299792458, 1.0, kind="alias-full"),
        row("o3-k095", "half", 146e6, 0.95, kind="length-factor"),
        row("o3-hf-quarter", "quarter", 28e6, 0.96, kind="hf"),
        row("o3-vhf-half", "half", 146e6, 1.0, kind="vhf"),
        row("o3-uhf-wavelength", "wavelength", 435e6, 0.95, kind="uhf"),
        row("o3-am-broadcast", "half", 1e6, 1.0, kind="lf"),
        row("o3-2m-k095", "quarter", 146e6, 0.95, kind="length-factor-quarter"),
    ]


def main() -> None:
    mp.mp.dps = DPS
    here = Path(__file__).resolve().parent
    table = {
        "family": "antenna_length",
        "generator_id": GENERATOR_ID,
        "generator_version": GENERATOR_VERSION,
        "seed": SEED,
        "mpmath_dps": DPS,
        "precision_bits": int(DPS * math.log2(10)),
        "library": f"mpmath {mp.__version__}",
        "c0_m_s": 299792458,
        "notes": "L=(c/f)·k·frac; independent of Node Math and the IUT.",
        "vectors": vectors(),
    }
    dest = here / "antenna-length-o3-tables.json"
    dest.write_text(json.dumps(table, indent=2) + "\n", encoding="utf-8")
    public = here.parents[3] / "public/developers/cvp/reproduce"
    public.mkdir(parents=True, exist_ok=True)
    shutil.copy2(dest, public / "antenna-length-o3-tables.json")
    shutil.copy2(Path(__file__), public / "generate-antenna-length-o3.py")
    print(f"wrote {dest} ({len(table['vectors'])} vectors)")


if __name__ == "__main__":
    main()
