#!/usr/bin/env python3
"""mpmath O3 for mechanical.statics.end_triangle_at_deflection."""
from __future__ import annotations
import json, math, shutil
from pathlib import Path
import mpmath as mp

def pick(inputs, *keys):
    for key in keys:
        if key in inputs and inputs[key] not in (None, ""):
            return mp.mpf(str(inputs[key]))
    return None

def compute(inputs):
    w0 = pick(inputs, "w0", "w", "intensity", "omega")
    x = pick(inputs, "x", "position", "s")
    L = pick(inputs, "L", "span", "length")
    E = pick(inputs, "E", "youngs", "modulus")
    I = pick(inputs, "I", "Ix", "inertia")
    xi = x if x <= (L - x) else (L - x)
    uniform = (w0 * x * (L**3 - 2 * L * x * x + x**3)) / (24 * E * I)
    center = (w0 * ((5 * L**3 / 192) * xi - (L / 24) * xi**3 + xi**5 / (60 * L))) / (E * I)
    delta = (3 * w0 * L**4) / (640 * E * I) if (x * 2 == L) else (uniform - center)
    return {"delta": delta, "w0": w0, "x": x, "L": L, "E": E, "I": I}

def row(vid, inputs, kind):
    out = compute(inputs)
    packed = {"id": vid, "kind": kind, "inputs": inputs}
    for k, v in out.items():
        packed[f"{k}_f64"] = float(v)
        packed[f"{k}_decimal"] = mp.nstr(v, 40, strip_zeros=False)
    return packed

def main():
    mp.mp.dps = 80
    here = Path(__file__).resolve().parent
    vectors = [
        row("o3-check", {"w0":"24","x":"1","L":"2","E":"1","I":"1"}, "check"),
        row("o3-SI", {"w0":"1000","x":"1","L":"2","E":"200000000000","I":"0.00001"}, "SI"),
        row("o3-alias", {"w":"48","span":"2","modulus":"1","Ix":"1","x":"1"}, "alias"),
        row("o3-awkward", {"w0":"13.7","x":"0.8","L":"2","E":"210000","I":"0.83"}, "awkward"),
        row("o3-neg", {"w0":"-24","x":"1","L":"2","E":"1","I":"1"}, "signed"),
        row("o3-small", {"w0":"10","x":"0.5","L":"2","E":"1000","I":"0.01"}, "small"),
        row("o3-stiff", {"w0":"500","x":"1","L":"2","E":"210e9","I":"2e-4"}, "stiff"),
        row("o3-long", {"w0":"200","x":"1","L":"4","E":"70e9","I":"5e-5"}, "long"),
    ]
    table = {
        "family": "end_triangle_at_deflection",
        "generator_id": "end-triangle-at-mpmath-o3",
        "generator_version": "1.0.0",
        "seed": "20260927.end-triangle-at-o3",
        "mpmath_dps": 80,
        "precision_bits": int(80 * math.log2(10)),
        "library": f"mpmath {mp.__version__}",
        "notes": "end-peaked triangle at station (uniform − center triangle); + O3 mpmath tabulated δ.",
        "vectors": vectors,
    }
    dest = here / "end-triangle-at-o3-tables.json"
    dest.write_text(json.dumps(table, indent=2) + chr(10), encoding="utf-8")
    public = here.parents[3] / "public/developers/cvp/reproduce"
    public.mkdir(parents=True, exist_ok=True)
    shutil.copy2(dest, public / "end-triangle-at-o3-tables.json")
    shutil.copy2(Path(__file__), public / "generate-end-triangle-at-o3.py")
    print(f"wrote {dest} ({len(vectors)} vectors)")

if __name__ == "__main__":
    main()
