/* ignition-scene.jsx — Chapter 9: the ignition coil, end to end.
   A self-running SVG animation of the full circuit: 12 V battery → switch
   ("the points") → coil, then a tap over to the spark plug seated in the
   cylinder. Both the battery and the engine block share a ground — that's the
   return path. Cycle: CHARGE (current builds, field grows) → CUT (points snap
   open) → SPARK (the collapse spike leaps the plug gap, fuel fires) → repeat.
   Names ign-prefixed. Uses CSS vars, theme-safe. */

function IgnGround({ x, y, ink }) {
  return (
    <g stroke={ink} strokeWidth="2.4" strokeLinecap="round">
      <line x1={x} y1={y} x2={x} y2={y + 10} />
      <line x1={x - 12} y1={y + 10} x2={x + 12} y2={y + 10} />
      <line x1={x - 7} y1={y + 15} x2={x + 7} y2={y + 15} />
      <line x1={x - 3} y1={y + 20} x2={x + 3} y2={y + 20} />
    </g>
  );
}

function IgnitionScene({ kids }) {
  const [running, setRunning] = React.useState(true);
  const [ph, setPh] = React.useState({ phase: "charge", p: 0 });
  const runRef = React.useRef(running); runRef.current = running;

  React.useEffect(() => {
    let raf, t0 = performance.now(), phase = "charge";
    const DUR = { charge: 2600, cut: 350, spark: 1100, rest: 800 };
    function tick(now) {
      if (!runRef.current) { t0 = now; raf = requestAnimationFrame(tick); return; }
      let el = now - t0;
      if (el >= DUR[phase]) {
        t0 = now; el = 0;
        phase = phase === "charge" ? "cut" : phase === "cut" ? "spark" : phase === "spark" ? "rest" : "charge";
      }
      setPh({ phase, p: el / DUR[phase] });
      raf = requestAnimationFrame(tick);
    }
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  const { phase, p } = ph;
  const cur = phase === "charge" ? 1 - Math.exp(-p * 3.2)
            : phase === "cut" ? Math.max(0, 0.96 * (1 - p * 1.4))
            : 0;
  const swOpen = phase === "charge" ? 0 : phase === "cut" ? Math.min(1, p * 1.8) : 1;
  const sparkA = phase === "spark" ? (p < 0.2 ? p / 0.2 : Math.max(0, 1 - (p - 0.2) / 0.8)) : 0;
  const flame = phase === "spark" ? Math.max(0, Math.min(1, (p - 0.18) / 0.45)) * (1 - Math.max(0, (p - 0.72) / 0.28)) : 0;
  const hot = sparkA > 0.08;              // "high voltage present" — paints the plug lead red
  const fieldR = 8 + cur * 26;
  const dash = -((performance.now() / 22) * cur) % 16;

  const label = phase === "charge" ? (kids ? "1 · filling the coil with push…" : "1 · CHARGE — current builds in the coil")
              : phase === "cut" ? (kids ? "2 · SNAP! the switch opens" : "2 · CUT — the points snap open · di/dt is huge")
              : phase === "spark" ? (kids ? "3 · the push leaps the gap — SPARK!" : "3 · SPARK — the collapse voltage jumps the plug gap")
              : (kids ? "…and again, every turn of the engine" : "…repeats every engine revolution");

  const ink = "var(--ink)", faint = "var(--ink-faint)", soft = "var(--ink-soft)";
  const RED = "oklch(0.55 0.19 30)", BLUE = "var(--water-deep)", AMB = "oklch(0.75 0.15 70)", HOTAMB = "oklch(0.85 0.16 85)";

  // geometry
  const TY = 110, BY = 250;               // top/bottom wire y
  const BX = 110;                          // battery x
  const S0 = 218, S1 = 268;                // points contacts
  const CX0 = 375, CX1 = 435;              // coil span
  const RX = 500;                          // loop right corner
  const PX = 640;                          // plug centre x
  const gapY = 168;                        // spark gap y
  const leadCol = hot ? RED : ink;

  return (
    <div>
      <svg viewBox="0 0 780 330" style={{ width: "100%", display: "block", background: "var(--bg-card)", border: "1px solid var(--rule)", borderRadius: 12 }}>
        {/* ── the primary loop: battery → points → coil → down → back ── */}
        {/* left wire, broken around the battery symbol */}
        <line x1={BX} y1={TY} x2={BX} y2={172} stroke={ink} strokeWidth="2.5" />
        <line x1={BX} y1={204} x2={BX} y2={BY} stroke={ink} strokeWidth="2.5" />
        {/* top + right + bottom */}
        <line x1={BX} y1={TY} x2={S0} y2={TY} stroke={ink} strokeWidth="2.5" />
        <line x1={S1} y1={TY} x2={CX0} y2={TY} stroke={ink} strokeWidth="2.5" />
        <line x1={CX1} y1={TY} x2={RX} y2={TY} stroke={ink} strokeWidth="2.5" />
        <line x1={RX} y1={TY} x2={RX} y2={BY} stroke={ink} strokeWidth="2.5" />
        <line x1={RX} y1={BY} x2={BX} y2={BY} stroke={ink} strokeWidth="2.5" />
        {/* flowing current dots */}
        {cur > 0.03 && (
          <path d={`M ${BX} ${TY} L ${S0} ${TY} M ${S1} ${TY} L ${RX} ${TY} L ${RX} ${BY} L ${BX} ${BY} L ${BX} 204 M ${BX} 172 L ${BX} ${TY}`}
                fill="none" stroke={BLUE} strokeWidth="4.5" strokeLinecap="round"
                strokeDasharray="2 14" strokeDashoffset={dash} opacity={0.3 + cur * 0.7} />
        )}
        {/* battery symbol */}
        <line x1={BX - 17} y1={178} x2={BX + 17} y2={178} stroke={ink} strokeWidth="3.6" />
        <line x1={BX - 9} y1={196} x2={BX + 9} y2={196} stroke={ink} strokeWidth="3.6" />
        <line x1={BX} y1={172} x2={BX} y2={178} stroke={ink} strokeWidth="2.5" />
        <line x1={BX} y1={196} x2={BX} y2={204} stroke={ink} strokeWidth="2.5" />
        <text x={BX - 26} y={192} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="12" fill={soft}>12 V</text>

        {/* the points (switch): a lever that snaps open */}
        <circle cx={S0} cy={TY} r="4" fill={ink} />
        <circle cx={S1} cy={TY} r="4" fill={ink} />
        <line x1={S0} y1={TY} x2={S0 + (S1 - S0) * Math.cos(swOpen * 0.75)} y2={TY - (S1 - S0) * Math.sin(swOpen * 0.75)}
              stroke={swOpen > 0.4 ? RED : ink} strokeWidth="4.5" strokeLinecap="round" />
        <text x={(S0 + S1) / 2} y={TY - 46} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="11"
              fill={swOpen > 0.4 ? RED : faint}>
          {kids ? (swOpen > 0.4 ? "OPEN!" : "the switch") : (swOpen > 0.4 ? "points OPEN" : "the points")}
        </text>

        {/* the coil */}
        <path d={`M ${CX0} ${TY} a 7.5 13 0 0 1 15 0 a 7.5 13 0 0 1 15 0 a 7.5 13 0 0 1 15 0 a 7.5 13 0 0 1 15 0`}
              fill="none" stroke={hot ? RED : ink} strokeWidth="3" strokeLinecap="round" />
        {cur > 0.05 && [1, 2, 3].map(k => (
          <ellipse key={k} cx={(CX0 + CX1) / 2} cy={TY - 7} rx={fieldR * k / 3} ry={fieldR * k / 4.6} fill="none"
                   stroke={BLUE} strokeWidth="1.5" opacity={(0.2 + 0.5 * cur) / k} />
        ))}
        <text x={(CX0 + CX1) / 2} y={TY - 52} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="11" fill={faint}>
          {kids ? "the coil" : "ignition coil (L)"}
        </text>

        {/* ── the plug lead: coil output, tapped over to the spark plug ── */}
        <line x1={RX} y1={TY} x2={PX} y2={TY} stroke={leadCol} strokeWidth="2.5" opacity={hot ? 1 : 0.6} />
        <line x1={PX} y1={TY} x2={PX} y2={128} stroke={leadCol} strokeWidth="2.5" opacity={hot ? 1 : 0.6} />
        {hot && (
          <text x={(RX + PX) / 2} y={TY - 12} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="12" fontWeight="600" fill={RED} opacity={Math.min(1, sparkA * 1.5)}>
            {kids ? "HUGE push!" : "~30,000 V"}
          </text>
        )}

        {/* ── the cylinder + spark plug ── */}
        <path d={`M 566 150 L 714 150 L 714 292 L 566 292 Z`} fill="var(--bg-deeper)" stroke={ink} strokeWidth="2" />
        <text x="640" y="310" textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="10" fill={faint}>
          {kids ? "inside the engine" : "engine cylinder (fuel + air)"}
        </text>
        {/* plug body straddling the cylinder wall */}
        <rect x={PX - 14} y={128} width="28" height="26" fill="var(--bg-card)" stroke={ink} strokeWidth="2" />
        <text x={PX + 22} y={140} fontFamily="IBM Plex Mono, monospace" fontSize="10" fill={faint}>{kids ? "spark plug" : "spark plug"}</text>
        {/* centre electrode down into the cylinder */}
        <line x1={PX} y1={154} x2={PX} y2={gapY - 5} stroke={hot ? RED : ink} strokeWidth="4" strokeLinecap="round" />
        {/* side electrode: hooks up from the plug shell (grounded via the block) */}
        <path d={`M ${PX + 13} 154 L ${PX + 13} ${gapY + 7} L ${PX + 2} ${gapY + 7}`} fill="none" stroke={ink} strokeWidth="4" strokeLinecap="round" />
        {/* the gap, labelled while charging so the eye knows where to look */}
        {phase === "charge" && (
          <text x={PX - 20} y={gapY + 6} textAnchor="end" fontFamily="IBM Plex Mono, monospace" fontSize="10" fill={faint}>
            {kids ? "tiny gap →" : "the gap →"}
          </text>
        )}
        {/* THE SPARK — a fat jagged bolt with a glow, leaping the gap */}
        {sparkA > 0.05 && (
          <g>
            <circle cx={PX} cy={gapY} r={10 + sparkA * 10} fill={HOTAMB} opacity={0.35 * sparkA} />
            <path d={`M ${PX} ${gapY - 5} l 4 4 l -6 2 l 6 4 l -3 2`}
                  fill="none" stroke={HOTAMB} strokeWidth="4.5" strokeLinecap="round" strokeLinejoin="round" opacity={Math.min(1, sparkA * 1.4)} />
            <path d={`M ${PX} ${gapY - 5} l 4 4 l -6 2 l 6 4 l -3 2`}
                  fill="none" stroke={RED} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" opacity={Math.min(1, sparkA * 1.4)} />
          </g>
        )}
        {/* ignition: layered flame bloom under the gap */}
        {flame > 0.02 && (
          <g>
            <circle cx={PX - 4} cy={gapY + 42} r={6 + flame * 40} fill={AMB} opacity={0.30 * flame} />
            <circle cx={PX - 4} cy={gapY + 42} r={4 + flame * 24} fill={HOTAMB} opacity={0.5 * flame} />
            <circle cx={PX - 4} cy={gapY + 42} r={2 + flame * 10} fill="oklch(0.93 0.1 95)" opacity={0.75 * flame} />
          </g>
        )}
        {flame > 0.3 && (
          <text x={PX} y={gapY + 108} textAnchor="middle" fontFamily="Newsreader, serif" fontStyle="italic" fontSize="15" fill={soft} opacity={flame}>
            {kids ? "boom! the engine fires" : "fuel ignites — the engine fires"}
          </text>
        )}

        {/* ── the shared ground: the return path ── */}
        <IgnGround x={290} y={BY} ink={ink} />
        <line x1={640} y1={292} x2={640} y2={296} stroke="none" />
        <IgnGround x={540} y={292} ink={ink} />
        <line x1={566} y1={292} x2={540} y2={292} stroke={ink} strokeWidth="2.4" />
        {!kids && (
          <text x={402} y={286} textAnchor="middle" fontFamily="IBM Plex Mono, monospace" fontSize="10" fill={faint}>
            shared ground — the spark's return path
          </text>
        )}
      </svg>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, marginTop: 10, flexWrap: "wrap" }}>
        <span style={{ fontFamily: "'IBM Plex Mono', monospace", fontSize: 12, color: phase === "spark" ? RED : "var(--ink-soft)" }}>{label}</span>
        <button onClick={() => setRunning(r => !r)}
                style={{ appearance: "none", whiteSpace: "nowrap", border: "1px solid var(--rule-strong)", background: "var(--bg-card)", color: "var(--ink)", borderRadius: 8, padding: "6px 14px", fontFamily: "'IBM Plex Mono', monospace", fontSize: 12, cursor: "pointer" }}>
          {running ? "❚❚ pause" : "▶ run"}
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { IgnitionScene });
