/* predatorpreylab.jsx — PredatorPreyTutor: the Lotka–Volterra predator–prey bench. Built on
   window.BenchKit (harness) + window.BenchFields (shared field math), so this file is just the
   FIGURE. computeFields = window.BenchFields.predatorPrey — the SAME function
   server/benches/predatorprey.js calls, so client and server fields are identical by construction.
   Follows the gaslawslab.jsx single-figure template. */
(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.predatorPrey(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 PredatorPreyFig({ task, setTask, tasks, report, event, done }) {
    const [preyN, setPreyN] = useState(100);
    const [predN, setPredN] = useState(20);
    const [preyGrowth, setPreyGrowth] = useState(0.5);
    const [predDeath, setPredDeath] = useState(0.3);
    const fld = useMemo(() => compute({ preyN, predN, preyGrowth, predDeath }), [preyN, predN, preyGrowth, predDeath]);
    useEffect(() => { report(fld); }, [preyN, predN, preyGrowth, predDeath]); // eslint-disable-line

    // two population bars: prey (max 200) and predator (max 100). Arrows show dPrey/dPred.
    const PREY_MAX = 200, PRED_MAX = 100;
    const AX0 = 70, AY0 = 40, AY1 = 250, BAR_W = 90;
    const preyX = 150, predX = 360;
    const preyH = (preyN / PREY_MAX) * (AY1 - AY0);
    const predH = (predN / PRED_MAX) * (AY1 - AY0);
    const eqPrey = fld.preyEquilibrium;                 // equilibrium prey level (γ/δ)
    const eqY = AY1 - Math.min(1, eqPrey / PREY_MAX) * (AY1 - AY0);
    // arrow magnitude scaled & clamped; direction from rate sign.
    const arrow = (d, x) => {
      const mag = Math.min(60, Math.abs(d) * 1.2) + 8;
      const up = d > 0;
      const baseY = up ? AY0 - 10 : AY1 + 10;
      const tipY = up ? baseY - mag : baseY + mag;
      const col = up ? C.teal : C.crimson;
      const head = up ? -7 : 7;
      return (
        <g>
          <line x1={x} y1={baseY} x2={x} y2={tipY} stroke={col} strokeWidth="3" />
          <polyline points={`${x - 6},${tipY - head} ${x},${tipY} ${x + 6},${tipY - head}`} fill="none" stroke={col} strokeWidth="3" />
        </g>
      );
    };
    const t = tasks.find((x) => x.id === task) || tasks[0];

    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={AX0} y1={AY1} x2={540} y2={AY1} stroke={C.faint} strokeWidth="1.5" />
          {/* equilibrium prey marker */}
          <line x1={preyX - 20} y1={eqY} x2={preyX + BAR_W + 20} y2={eqY} stroke={C.gold} strokeWidth="1.5" strokeDasharray="5 4" />
          <text x={preyX + BAR_W + 26} y={eqY + 4} fill={C.gold} fontSize="10" fontFamily="monospace">N* = {fmt(eqPrey)}</text>
          {/* prey bar */}
          <rect x={preyX} y={AY1 - preyH} width={BAR_W} height={preyH} fill={C.teal} opacity="0.6" rx="3" />
          <text x={preyX + BAR_W / 2} y={AY1 + 20} textAnchor="middle" fill={C.mute} fontSize="11" fontFamily="monospace">prey {Math.round(preyN)}</text>
          {arrow(fld.dPrey, preyX + BAR_W / 2)}
          {/* predator bar */}
          <rect x={predX} y={AY1 - predH} width={BAR_W} height={predH} fill={C.crimson} opacity="0.55" rx="3" />
          <text x={predX + BAR_W / 2} y={AY1 + 20} textAnchor="middle" fill={C.mute} fontSize="11" fontFamily="monospace">predator {Math.round(predN)}</text>
          {arrow(fld.dPred, predX + BAR_W / 2)}
          {/* phase indicator */}
          <text x={AX0} y={AY0 - 14} fill={C.ink} fontSize="11" fontFamily="monospace">
            {fld.atEquilibrium ? "● at equilibrium" : `prey ${fld.preyGrowing ? "↑" : "↓"} · predator ${fld.predGrowing ? "↑" : "↓"}`}
          </text>
        </svg>
        <div style={{ marginTop: 10, padding: "8px 12px", borderRadius: 6, background: C.panel, border: `1px solid ${fld.atEquilibrium ? C.teal : C.line}`, color: fld.atEquilibrium ? C.teal : C.mute, fontSize: 12.5 }}>
          dPrey/dt = αN − βNP = {fmt(fld.dPrey)} · dPred/dt = δNP − γP = {fmt(fld.dPred)} (β = δ = 0.01).
          {fld.atEquilibrium ? " ✓ coexistence equilibrium — neither population changes." : " Set prey = γ/0.01 and predators = α/0.01 to balance the system."}
        </div>
        <Slider label="prey N" value={preyN} set={setPreyN} min={10} max={200} step={5} color={C.teal} onUp={() => event("adjusted", `Set prey = ${Math.round(preyN)}`, { response: `dPrey ${fmt(fld.dPrey)}` }, C.teal)} />
        <Slider label="predator P" value={predN} set={setPredN} min={1} max={100} step={1} color={C.crimson} onUp={() => event("adjusted", `Set predators = ${Math.round(predN)}`, { response: `dPred ${fmt(fld.dPred)}` }, C.crimson)} />
        <Slider label="prey growth α" value={preyGrowth} set={setPreyGrowth} min={0.1} max={1} step={0.05} color={C.blue} onUp={() => event("adjusted", `Set α = ${fmt(preyGrowth)}`, { response: `dPrey ${fmt(fld.dPrey)}` }, C.blue)} />
        <Slider label="predator death γ" value={predDeath} set={setPredDeath} min={0.1} max={1} step={0.05} color={C.gold} onUp={() => event("adjusted", `Set γ = ${fmt(predDeath)}`, { response: `N* ${fmt(fld.preyEquilibrium)}` }, C.gold)} />
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 8, marginTop: 12 }}>
          <StatMeter label="dPrey/dt" v={fld.dPrey} d={1} color={fld.preyGrowing ? C.teal : C.crimson} />
          <StatMeter label="dPred/dt" v={fld.dPred} d={1} color={fld.predGrowing ? C.teal : C.crimson} />
          <StatMeter label="prey eq N*" v={fld.preyEquilibrium} d={1} color={C.gold} />
          <StatMeter label="predator P" v={predN} d={0} color={C.crimson} />
        </div>
      </>
    );
  }

  window.PredatorPreyTutor = K.makeTutor(PredatorPreyFig, { moduleLabel: "Predator–prey bench", benchId: "predatorprey" });
})();
