/* greenhouselab.jsx — GreenhouseTutor: the climate energy-balance bench. Built on
   window.BenchKit (harness) + window.BenchFields (shared field math), so this file is
   just the FIGURE. compute = window.BenchFields.greenhouse — the SAME function
   server/benches/greenhouse.js calls, so client and server fields are identical by
   construction. Mirrors the gaslawslab.jsx 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.greenhouse(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 GreenhouseFig({ task, setTask, tasks, report, event, done }) {
    const [solarConstant, setSolar] = useState(1361);
    const [albedo, setAlbedo] = useState(0.3);
    const [greenhouseFactor, setGreen] = useState(0.3);
    const fld = useMemo(() => compute({ solarConstant, albedo, greenhouseFactor }), [solarConstant, albedo, greenhouseFactor]);
    useEffect(() => { report(fld); }, [solarConstant, albedo, greenhouseFactor]); // eslint-disable-line

    const eq = fld.equilibTemp;
    // disc color: cold (blue) → temperate (teal) → hot (crimson), tracking equilibTemp.
    const warmth = Math.max(0, Math.min(1, (eq + 60) / 120));   // -60°C..+60°C → 0..1
    const discColor = eq <= -20 ? C.blue : (eq >= 50 ? C.crimson : C.teal);
    const sunCount = Math.max(2, Math.round((solarConstant - 200) / 200) + 2);
    const reflFrac = albedo;            // 0..0.9
    const ghOpacity = 0.1 + greenhouseFactor * 1.6;   // greenhouse-layer opacity ∝ factor

    // planet center
    const PX = 300, PY = 200, PR = 70;
    // sun arrows come from top-left toward the planet
    const sun = [];
    for (let i = 0; i < sunCount; i++) {
      const x = 60 + i * (180 / Math.max(1, sunCount));
      sun.push(x);
    }
    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 }}>
          {/* space label */}
          <text x={14} y={22} fill={C.mute} fontSize="11" fontFamily="monospace">S = {Math.round(solarConstant)} W/m² · α = {fmt(albedo)} · gh = {fmt(greenhouseFactor)}</text>
          {/* incoming sunlight arrows (gold) */}
          {sun.map((x, i) => (
            <line key={"in" + i} x1={x} y1={20} x2={x + 90} y2={120} stroke={C.gold} strokeWidth="2.5" opacity="0.85" markerEnd="url(#ghArrow)" />
          ))}
          {/* reflected sunlight (opacity ∝ albedo) */}
          {sun.map((x, i) => (
            <line key={"ref" + i} x1={x + 90} y1={120} x2={x + 30} y2={26} stroke={C.gold} strokeWidth="2" opacity={0.15 + reflFrac * 0.75} markerEnd="url(#ghArrow)" />
          ))}
          {/* greenhouse-gas layer arc above the planet, opacity ∝ greenhouse factor */}
          <path d={`M ${PX - 140} ${PY - 110} Q ${PX} ${PY - 160} ${PX + 140} ${PY - 110}`} fill="none" stroke={C.amber} strokeWidth={6} opacity={Math.min(0.9, ghOpacity)} />
          <text x={PX + 150} y={PY - 108} fill={C.amber} fontSize="10" fontFamily="monospace" opacity={Math.min(0.9, 0.3 + ghOpacity)}>IR-trapping layer</text>
          {/* outgoing infrared arrows (crimson), partly trapped → shorter when greenhouse high */}
          {[-1, 0, 1].map((k) => {
            const ox = PX + k * 40;
            const reach = 70 - greenhouseFactor * 90;   // 70 (no gh) → 25 (max gh)
            return <line key={"ir" + k} x1={ox} y1={PY - PR + 4} x2={ox} y2={PY - PR - Math.max(18, reach)} stroke={C.crimson} strokeWidth="2.5" opacity="0.8" markerEnd="url(#ghArrow)" />;
          })}
          {/* the planet disc, color ∝ equilibTemp */}
          <circle cx={PX} cy={PY} r={PR} fill={discColor} opacity={0.25 + warmth * 0.5} stroke={discColor} strokeWidth="2" />
          <text x={PX} y={PY - 2} textAnchor="middle" fill={C.ink} fontSize="16" fontFamily="monospace">{fmt(eq)} °C</text>
          <text x={PX} y={PY + 18} textAnchor="middle" fill={C.mute} fontSize="11" fontFamily="monospace">T_eff {Math.round(fld.effectiveTemp)} K</text>
          <text x={PX} y={PY + PR + 22} textAnchor="middle" fill={fld.isHabitable ? C.teal : C.crimson} fontSize="12" fontFamily="monospace">{fld.isHabitable ? "habitable" : "not habitable"}</text>
          <defs>
            <marker id="ghArrow" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
              <path d="M0,0 L6,3 L0,6 Z" fill={C.mute} />
            </marker>
          </defs>
        </svg>
        <div style={{ marginTop: 10, padding: "8px 12px", borderRadius: 6, background: C.panel, border: `1px solid ${fld.isHabitable ? C.line : C.crimson}`, color: fld.isHabitable ? C.mute : C.crimson, fontSize: 12.5 }}>
          absorbed = S(1−α)/4 = {Math.round(fld.absorbed)} W/m² · greenhouse forcing +{fmt(fld.forcing)} K. {fld.isHabitable ? "Within the habitable range." : "⚠ outside the habitable range."}
        </div>
        <Slider label="solar flux S" value={solarConstant} set={setSolar} min={200} max={2000} step={10} unit="W/m²" color={C.gold} onUp={() => event("adjusted", `Set S = ${Math.round(solarConstant)} W/m²`, { response: `T ${fmt(fld.equilibTemp)} °C` }, C.gold)} />
        <Slider label="albedo α" value={albedo} set={setAlbedo} min={0} max={0.9} step={0.05} unit="" color={C.blue} onUp={() => event("adjusted", `Set α = ${fmt(albedo)}`, { response: `T ${fmt(fld.equilibTemp)} °C` }, C.blue)} />
        <Slider label="greenhouse" value={greenhouseFactor} set={setGreen} min={0} max={0.5} step={0.05} unit="" color={C.crimson} onUp={() => event("adjusted", `Set greenhouse = ${fmt(greenhouseFactor)}`, { response: `T ${fmt(fld.equilibTemp)} °C` }, C.crimson)} />
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", gap: 8, marginTop: 12 }}>
          <StatMeter label="equilibrium T" v={fld.equilibTemp} d={1} unit="°C" color={discColor} />
          <StatMeter label="effective T" v={fld.effectiveTemp} d={0} unit="K" color={C.blue} />
          <StatMeter label="absorbed" v={fld.absorbed} d={0} unit="W/m²" color={C.gold} />
          <StatMeter label="forcing" v={fld.forcing} d={1} unit="K" color={C.crimson} />
        </div>
      </>
    );
  }

  window.GreenhouseTutor = K.makeTutor(GreenhouseFig, { moduleLabel: "Climate energy balance bench", benchId: "greenhouse" });
})();
