/* probabilitylab.jsx — ProbabilityTutor: the normal-distribution bench. Built on
   window.BenchKit (harness) + window.BenchFields (shared field math), so this file is just
   the FIGURE. computeFields = window.BenchFields.probability — the SAME function
   server/benches/probability.js calls, so client and server fields are identical by
   construction. Mirrors gaslawslab.jsx: sliders → BenchFields.fn(state) → report + meters. */
(function () {
  const { useState, useMemo, useEffect } = React;
  const K = window.BenchKit, C = K.C, SVG_BG = K.SVG_BG, fmt = K.fmt;
  const TaskStrip = K.TaskStrip, StatMeter = K.StatMeter;
  const compute = (s) => window.BenchFields.probability(s);

  function Slider({ label, value, set, min, max, step, unit, color, onUp }) {
    return (
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 9 }}>
        <span style={{ fontSize: 12, color: C.mute, width: 116 }}>{label}</span>
        <input type="range" min={min} max={max} step={step} value={value} onChange={(e) => set(parseFloat(e.target.value))} onPointerUp={onUp} style={{ flex: 1 }} />
        <span style={{ color: color || C.amber, width: 64, textAlign: "right" }}>{value}{unit ? ` ${unit}` : ""}</span>
      </div>
    );
  }

  function ProbabilityFig({ task, setTask, tasks, report, event, done }) {
    const [mean, setMean] = useState(0);
    const [sd, setSd] = useState(1);
    const [xCut, setXCut] = useState(1);
    const fld = useMemo(() => compute({ mean, sd, xCut }), [mean, sd, xCut]);
    useEffect(() => { report(fld); }, [mean, sd, xCut]); // eslint-disable-line

    // plot window: x in [mean − 4σ, mean + 4σ] maps to [X0..X1]; bell height ∝ Gaussian.
    const X0 = 70, X1 = 540, BASE = 250, TOP = 60;
    const span = 4 * sd;
    const xLo = mean - span, xHi = mean + span;
    const sx = (x) => X0 + ((x - xLo) / (xHi - xLo)) * (X1 - X0);
    const gauss = (x) => Math.exp(-0.5 * ((x - mean) / sd) ** 2); // peak 1 at the mean
    const sy = (g) => BASE - g * (BASE - TOP);

    // sample the curve across the view.
    const N = 120, pts = [];
    for (let i = 0; i <= N; i++) {
      const x = xLo + (i / N) * (xHi - xLo);
      pts.push([sx(x), sy(gauss(x))]);
    }
    const curve = pts.map((p) => `${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(" ");
    // shaded LEFT region (probBelow): from xLo up to the cut, clamped to the view.
    const cutClamped = Math.max(xLo, Math.min(xHi, xCut));
    const fill = [`${sx(xLo)},${BASE}`];
    for (let i = 0; i <= N; i++) {
      const x = xLo + (i / N) * (xHi - xLo);
      if (x > cutClamped) break;
      fill.push(`${sx(x).toFixed(1)},${sy(gauss(x)).toFixed(1)}`);
    }
    fill.push(`${sx(cutClamped)},${BASE}`);

    const cutX = sx(cutClamped);
    const muX = sx(mean), loX = sx(mean - sd), hiX = sx(mean + sd);
    const t = tasks.find((x) => x.id === task) || tasks[0];
    const z = fld.zScore, extreme = fld.isExtreme;

    return (
      <>
        <TaskStrip tasks={tasks} cur={task} setCur={setTask} done={done} goal={t && t.goal} />
        <svg viewBox="0 0 600 300" style={{ width: "100%", background: SVG_BG, border: `1px solid ${C.line}`, borderRadius: 8 }}>
          {/* baseline */}
          <line x1={X0} y1={BASE} x2={X1} y2={BASE} stroke={C.faint} strokeWidth="1.5" />
          {/* shaded probBelow region (left of the cut) */}
          <polygon points={fill.join(" ")} fill={C.blue} opacity="0.28" />
          {/* bell curve */}
          <polyline points={curve} fill="none" stroke={C.teal} strokeWidth="2" />
          {/* ±1σ markers */}
          <line x1={loX} y1={BASE} x2={loX} y2={BASE + 6} stroke={C.mute} strokeWidth="1.5" />
          <line x1={hiX} y1={BASE} x2={hiX} y2={BASE + 6} stroke={C.mute} strokeWidth="1.5" />
          <text x={loX} y={BASE + 18} textAnchor="middle" fill={C.mute} fontSize="10" fontFamily="monospace">−1σ</text>
          <text x={hiX} y={BASE + 18} textAnchor="middle" fill={C.mute} fontSize="10" fontFamily="monospace">+1σ</text>
          {/* mean marker */}
          <line x1={muX} y1={TOP} x2={muX} y2={BASE} stroke={C.gold} strokeWidth="1" strokeDasharray="3 3" />
          <text x={muX} y={TOP - 4} textAnchor="middle" fill={C.gold} fontSize="11" fontFamily="monospace">μ = {fmt(mean)}</text>
          {/* cut line at x */}
          <line x1={cutX} y1={TOP - 10} x2={cutX} y2={BASE} stroke={extreme ? C.crimson : C.amber} strokeWidth="2" />
          <text x={cutX} y={BASE + 30} textAnchor="middle" fill={extreme ? C.crimson : C.amber} fontSize="11" fontFamily="monospace">x = {fmt(xCut)}</text>
          {/* labels */}
          <text x={X0 + 6} y={TOP + 4} fill={C.mute} fontSize="11" fontFamily="monospace">σ = {fmt(sd)} · z = {fmt(z)}</text>
          <text x={sx(xLo) + (cutX - sx(xLo)) / 2} y={BASE - 8} textAnchor="middle" fill={C.blue} fontSize="12" fontFamily="monospace">{fld.percentile}th pct</text>
        </svg>
        <div style={{ marginTop: 10, padding: "8px 12px", borderRadius: 6, background: C.panel, border: `1px solid ${extreme ? C.crimson : C.line}`, color: extreme ? C.crimson : C.mute, fontSize: 12.5 }}>
          z = (x − μ)/σ = {fmt(z)} · P(X&lt;x) = {fmt(fld.probBelow)}. {extreme ? "⚠ extreme value (|z| ≥ 2)." : (fld.withinOneSD ? "Within one SD of the mean." : "Slide x past ±2σ for an extreme value.")}
        </div>
        <Slider label="mean μ" value={mean} set={setMean} min={-5} max={5} step={0.5} unit="" color={C.gold} onUp={() => event("adjusted", `Set μ = ${fmt(mean)}`, { response: `z ${fmt(fld.zScore)}` }, C.gold)} />
        <Slider label="std dev σ" value={sd} set={setSd} min={0.5} max={5} step={0.5} unit="" color={C.teal} onUp={() => event("adjusted", `Set σ = ${fmt(sd)}`, { response: `z ${fmt(fld.zScore)}` }, C.teal)} />
        <Slider label="cut value x" value={xCut} set={setXCut} min={-10} max={10} step={0.5} unit="" color={C.amber} onUp={() => event("adjusted", `Set x = ${fmt(xCut)}`, { response: `z ${fmt(fld.zScore)} · ${fld.percentile}th pct` }, C.amber)} />
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 8, marginTop: 12 }}>
          <StatMeter label="z-score" v={fld.zScore} d={2} color={extreme ? C.crimson : C.teal} />
          <StatMeter label="P(X<x)" v={fld.probBelow} d={3} color={C.blue} />
          <StatMeter label="P(X>x)" v={fld.probAbove} d={3} color={C.amber} />
          <StatMeter label="percentile" v={fld.percentile} d={0} color={C.gold} />
        </div>
      </>
    );
  }

  window.ProbabilityTutor = K.makeTutor(ProbabilityFig, { moduleLabel: "Normal distribution bench", benchId: "probability" });
})();
