#!/usr/bin/env python3
"""mpmath O3 for mechanical.statics.bending_stress. σ = M/S."""
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 row(vid, inputs, kind):
    M = pick(inputs, "M", "moment")
    S = pick(inputs, "S", "section_modulus")
    Ix = pick(inputs, "Ix", "I")
    c = pick(inputs, "c", "cy", "cx")
    if S is None:
        S = Ix / c
    sigma = M / S
    out = {
        "id": vid,
        "kind": kind,
        "inputs": inputs,
        "sigma_f64": float(sigma),
        "sigma_decimal": mp.nstr(sigma, 40, strip_zeros=False),
        "M_f64": float(M),
        "M_decimal": mp.nstr(M, 40, strip_zeros=False),
        "S_f64": float(S),
        "S_decimal": mp.nstr(S, 40, strip_zeros=False),
    }
    if Ix is not None:
        out["Ix_f64"] = float(Ix)
        out["c_f64"] = float(c)
    return out


def main():
    mp.mp.dps = 80
    here = Path(__file__).resolve().parent
    vectors = [
        row("o3-MS", {"M": "12", "S": "4"}, "S"),
        row("o3-Ix", {"M": "100", "Ix": "50", "c": "2"}, "Ix"),
        row("o3-alias", {"moment": "24", "section_modulus": "8"}, "alias"),
        row("o3-awkward", {"M": "12.5", "S": "3.7"}, "awkward"),
        row("o3-I-alias", {"M": "40", "I": "20", "cy": "2"}, "I"),
        row("o3-neg-M", {"M": "-18", "S": "6"}, "signed"),
        row("o3-small", {"M": "0.08", "S": "0.02"}, "small"),
        row("o3-large", {"M": "1e6", "S": "2500"}, "large"),
    ]
    table = {
        "family": "bending_stress",
        "generator_id": "bending-stress-mpmath-o3",
        "generator_version": "1.0.0",
        "seed": "20260927.bending-stress-o3",
        "mpmath_dps": 80,
        "precision_bits": int(80 * math.log2(10)),
        "library": f"mpmath {mp.__version__}",
        "notes": "σ = M/S. S may be Ix/c. Not plastic modulus, not rectangle b·h.",
        "vectors": vectors,
    }
    dest = here / "bending-stress-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 / "bending-stress-o3-tables.json")
    shutil.copy2(Path(__file__), public / "generate-bending-stress-o3.py")
    print(f"wrote {dest} ({len(vectors)} vectors)")


if __name__ == "__main__":
    main()
