"""Create a documented one-variable MHD ledger figure; assumptions only."""
import csv
from pathlib import Path

ROOT = Path(__file__).resolve().parent
FLOW, AVAILABLE, AUX = 10.0, 100.0, 20.0
SCENARIOS = [
    ("Reference teaching assumptions", .60, .60, 15.0, "#43c5ed"),
    ("Higher selected efficiencies; no field debit", .80, .80, 0.0, "#f276d2"),
    ("Lower selected efficiencies; 60 kW field debit", .40, .40, 60.0, "#a4da8a"),
]
FRACTIONS = [i / 100 for i in range(61)]

def calc(frac, eta_g, eta_a, field):
    removed = FLOW * AVAILABLE * frac
    electric = removed * eta_g
    accelerator = max(0.0, electric - AUX - field)
    returned = accelerator * eta_a
    return removed, electric, returned, -removed + returned

with (ROOT / "mhd-ledger-scenarios.csv").open("w", newline="", encoding="utf-8") as f:
    w = csv.writer(f)
    w.writerow(["extraction_fraction", "scenario", "generator_efficiency_assumption", "accelerator_efficiency_assumption", "field_excitation_power_assumption_kW", "removed_flow_power_kW", "generator_electric_output_kW", "accelerator_work_returned_kW", "net_stream_energy_change_kW"])
    for frac in FRACTIONS:
        for name, eg, ea, field, _ in SCENARIOS:
            removed, electric, returned, delta = calc(frac, eg, ea, field)
            w.writerow([f"{frac:.2f}", name, eg, ea, f"{field:.1f}", f"{removed:.3f}", f"{electric:.3f}", f"{returned:.3f}", f"{delta:.3f}"])

def svg(phone=False):
    width, height = (620, 890) if phone else (1000, 640)
    left, top = ((105, 170) if phone else (115, 145))
    pw, ph = ((455, 360) if phone else (760, 365))
    x = lambda f: left + f / .6 * pw
    y = lambda v: top + (-v / 650) * ph
    parts = [f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0 {width} {height}" role="img" aria-labelledby="title desc">',
             '<title id="title">MHD teaching-model stream-energy change</title>',
             '<desc id="desc">Three calculated lines plot stream-energy change against extraction fraction for separate fixed teaching assumptions. All lines are zero or negative. This is a simple ledger, not experimental data or a complete engine balance.</desc>',
             '<rect width="100%" height="100%" rx="18" fill="#07152e"/>',
             '<g font-family="Arial, sans-serif" fill="#edf4ff">',
             f'<text x="{left}" y="38" font-size="{20 if phone else 25}" font-weight="700">{"MHD model: stream-energy change" if phone else "Stream-energy change in an MHD teaching ledger"}</text>',
             f'<text x="{left}" y="67" font-size="{15 if phone else 16}" fill="#b9c8e2">{"Flow: 10 kg/s · assumed available energy: 100 kJ/kg" if phone else "Fixed flow 10 kg/s · assumed accessible energy 100 kJ/kg · other auxiliaries 20 kW"}</text>']
    if phone:
        parts.append(f'<text x="{left}" y="87" font-size="15" fill="#b9c8e2">Other auxiliary load: 20 kW · scenarios below</text>')
    for val in range(0, -651, -100):
        yy = y(val)
        parts += [f'<line x1="{left}" y1="{yy:.1f}" x2="{left+pw}" y2="{yy:.1f}" stroke="#395074" stroke-width="1"/>',
                  f'<text x="{left-9}" y="{yy+5:.1f}" text-anchor="end" font-size="16" fill="#b9c8e2">{val}</text>']
    for pct in range(0, 61, 10):
        xx = x(pct / 100)
        parts += [f'<line x1="{xx:.1f}" y1="{top}" x2="{xx:.1f}" y2="{top+ph}" stroke="#253d60" stroke-width="1"/>',
                  f'<text x="{xx:.1f}" y="{top+ph+23}" text-anchor="middle" font-size="16" fill="#b9c8e2">{pct}%</text>']
    parts += [f'<line x1="{left}" y1="{top}" x2="{left}" y2="{top+ph}" stroke="#aabbd5"/>',
              f'<line x1="{left}" y1="{top+ph}" x2="{left+pw}" y2="{top+ph}" stroke="#aabbd5"/>',
              f'<text transform="translate(28 {top+ph/2}) rotate(-90)" text-anchor="middle" font-size="17" fill="#edf4ff">Change in stream energy (kW)</text>',
              f'<text x="{left+pw/2}" y="{top+ph+49}" text-anchor="middle" font-size="17" fill="#edf4ff">Fraction removed from stream</text>']
    for name, eg, ea, field, color in SCENARIOS:
        d = " ".join(("M" if i == 0 else "L") + f"{x(frac):.1f},{y(calc(frac,eg,ea,field)[3]):.1f}" for i, frac in enumerate(FRACTIONS))
        parts.append(f'<path d="{d}" fill="none" stroke="{color}" stroke-width="4"/>')
    legend_y = top + ph + (70 if phone else 28)
    for i, (name, eg, ea, field, color) in enumerate(SCENARIOS):
        ly = legend_y + i * (60 if phone else 27)
        result20 = calc(.2, eg, ea, field)[3]
        result60 = calc(.6, eg, ea, field)[3]
        short_name = {"Reference teaching assumptions":"Reference", "Higher selected efficiencies; no field debit":"Higher-efficiency assumptions", "Lower selected efficiencies; 60 kW field debit":"Lower-efficiency assumptions"}[name]
        label = f"{short_name} · ηg {eg:.0%}, ηa {ea:.0%}, field {field:g} kW"
        parts += [f'<line x1="{left}" y1="{ly-4}" x2="{left+24}" y2="{ly-4}" stroke="{color}" stroke-width="4"/>',
                  f'<text x="{left+32}" y="{ly}" font-size="{15 if phone else 14}" fill="#edf4ff">{label}</text>']
        if phone:
            parts += [f'<text x="{left+32}" y="{ly+16}" font-size="15" fill="#b9c8e2">ηg {eg:.0%} · ηa {ea:.0%} · field {field:g} kW</text>',
                      f'<text x="{left+32}" y="{ly+32}" font-size="15" fill="#b9c8e2">20%: {result20:.0f} kW · 60%: {result60:.0f} kW</text>']
        else:
            parts.append(f'<text x="{left+470}" y="{ly}" font-size="16" fill="#b9c8e2">at 20%: {result20:.0f} kW · at 60%: {result60:.0f} kW</text>')
    if phone:
        parts += [f'<text x="{left}" y="{height-38}" font-size="15" fill="#ffb8df">Model arithmetic only · not measured data.</text>', f'<text x="{left}" y="{height-18}" font-size="15" fill="#ffb8df">No pressure, momentum, heat or vehicle balance.</text>']
    else:
        parts.append(f'<text x="{left}" y="{height-22}" font-size="14" fill="#ffb8df">Model arithmetic only · not measured data · no pressure, momentum, heat or vehicle balance</text>')
    parts.append('</g></svg>')
    return "".join(parts)

(ROOT / "mhd-ledger-scenarios.svg").write_text(svg(), encoding="utf-8")
(ROOT / "mhd-ledger-scenarios-mobile.svg").write_text(svg(True), encoding="utf-8")

# Property checks over the full sweep and scenario endpoints.
for name, eg, ea, field, _ in SCENARIOS:
    deltas = [calc(frac, eg, ea, field)[3] for frac in FRACTIONS]
    assert len(deltas) == 61 and deltas[0] == 0
    assert all(value <= 1e-9 for value in deltas)
    assert all(b <= a + 1e-9 for a, b in zip(deltas, deltas[1:]))
for eg in (0, .4, .6, .8, 1):
    for ea in (0, .4, .6, .8, 1):
        for field in (0, 15, 60, 1000):
            for frac in FRACTIONS:
                removed, electric, returned, delta = calc(frac, eg, ea, field)
                assert removed >= 0 and electric >= 0 and returned >= 0
                assert returned <= electric + 1e-9 and delta <= 1e-9
print("MHD scenario plot generated: 183 explicit assumptions rows; 61-point monotonic checks and 6,100 boundary/property cases passed.")
