/* anim-finale.jsx — Animations for the final batch of topics */

/* ===== Human-in-the-loop with interrupt() ===== */
const HITLSim = () => {
  const STEPS = [
    { phase: "running", node: "draft_email", desc: "Agent drafts email to customer" },
    { phase: "interrupt", node: "review", desc: "interrupt() · graph paused · state checkpointed" },
    { phase: "ui", node: "review", desc: "UI shows draft to human · awaits approval" },
    { phase: "edit", node: "review", desc: "Human edits subject line, hits Approve" },
    { phase: "resume", node: "send_email", desc: "graph.invoke(None, config) · resumes from checkpoint" },
    { phase: "running", node: "send_email", desc: "Email sent ✓" },
  ];
  const { step, containerRef } = useStepper({ steps: STEPS.length, intervalMs: 1700 });
  const cur = STEPS[step];
  const paused = ["interrupt", "ui", "edit"].includes(cur.phase);

  return (
    <div ref={containerRef}>
      <div style={{ display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 20 }}>
        <svg viewBox="0 0 480 220" style={{ width: "100%", height: "auto", background: "#fbfbfa", borderRadius: 8, border: "1px solid #e7e7e2" }}>
          {[
            { id: "draft_email", x: 80,  y: 110, label: "draft_email" },
            { id: "review",      x: 240, y: 110, label: "review" },
            { id: "send_email",  x: 400, y: 110, label: "send_email" },
          ].map((n, i, arr) => {
            const active = cur.node === n.id;
            const isReview = n.id === "review";
            const reviewPaused = isReview && paused;
            return (
              <g key={n.id}>
                {active && (
                  <circle cx={n.x} cy={n.y} r="46" fill="none" stroke={reviewPaused ? "#c7521c" : "#2d5fb8"} strokeWidth="1.5" opacity="0.4">
                    <animate attributeName="r" from="34" to="50" dur={reviewPaused ? "2s" : "1.2s"} repeatCount="indefinite" />
                    <animate attributeName="opacity" from="0.5" to="0" dur={reviewPaused ? "2s" : "1.2s"} repeatCount="indefinite" />
                  </circle>
                )}
                <circle cx={n.x} cy={n.y} r="36"
                  fill={active ? (reviewPaused ? "#fbeadc" : "#e8f0fe") : "#fff"}
                  stroke={active ? (reviewPaused ? "#c7521c" : "#2d5fb8") : "#c7c7c0"}
                  strokeWidth={active ? 2 : 1.2} style={{ transition: "all 0.3s" }} />
                <text x={n.x} y={n.y + 4} textAnchor="middle"
                  fontSize="10" fontFamily="JetBrains Mono, monospace"
                  fill={active ? (reviewPaused ? "#c7521c" : "#2d5fb8") : "#1a1a1a"} fontWeight="600">{n.label}</text>
                {i < arr.length - 1 && (
                  <line x1={n.x + 36} y1={n.y} x2={arr[i+1].x - 36} y2={n.y}
                    stroke={cur.node === arr[i+1].id || (i === 1 && cur.phase === "resume") ? "#2d5fb8" : "#c7c7c0"}
                    strokeWidth="1.5" markerEnd="url(#hitl-arr)" />
                )}
              </g>
            );
          })}
          {paused && (
            <g>
              <rect x={196} y={42} width="88" height="20" rx="3" fill="#c7521c" />
              <text x={240} y={56} textAnchor="middle" fontSize="10" fill="#fff" fontFamily="JetBrains Mono, monospace" fontWeight="600">PAUSED</text>
            </g>
          )}
          <defs><marker id="hitl-arr" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#2d5fb8" /></marker></defs>
        </svg>

        <div>
          <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 11, color: "#6b6b66", marginBottom: 10, textTransform: "uppercase", letterSpacing: "0.06em" }}>checkpointer state</div>
          <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 6, padding: 12, fontFamily: "JetBrains Mono, monospace", fontSize: 11, color: "#1a1a1a", lineHeight: 1.7 }}>
            <div style={{ color: "#a3a39d" }}>thread_id: <span style={{ color: "#1a1a1a" }}>"t_8a3f"</span></div>
            <div style={{ color: "#a3a39d" }}>node: <span style={{ color: "#2d5fb8" }}>"{cur.node}"</span></div>
            <div style={{ color: "#a3a39d" }}>status: <span style={{ color: paused ? "#c7521c" : "#2e7d4f" }}>{paused ? "paused" : "running"}</span></div>
            {step >= 1 && <div style={{ color: "#a3a39d", marginTop: 6 }}>draft: <span style={{ color: "#1a1a1a" }}>{step >= 3 ? '"[edited] Welcome aboard!"' : '"Welcome aboard!"'}</span></div>}
            {step >= 4 && <div style={{ color: "#a3a39d" }}>approved: <span style={{ color: "#2e7d4f" }}>true</span></div>}
            {step === 5 && <div style={{ color: "#a3a39d" }}>message_id: <span style={{ color: "#1a1a1a" }}>"msg_5f2c"</span></div>}
          </div>
          <div style={{ marginTop: 12, padding: "10px 12px", background: paused ? "#fbeadc" : "#e3f1e8", border: `1px solid ${paused ? "#ecd690" : "#b8dcc4"}`, borderRadius: 4, fontSize: 12, color: paused ? "#c7521c" : "#2e7d4f" }}>
            {cur.desc}
          </div>
        </div>
      </div>
    </div>
  );
};

/* ===== Time-travel · branching from a past checkpoint ===== */
const TimeTravelSim = () => {
  const TIMELINE = [
    { id: "c1", node: "classify", time: "+0.2s", state: "intent: book_flight" },
    { id: "c2", node: "search",   time: "+1.4s", state: "results: [SF→NYC]" },
    { id: "c3", node: "respond",  time: "+3.1s", state: "answer: [bad — too short]" },
  ];
  const STEPS = [
    { focus: 0, action: "run completes — answer was poor" },
    { focus: 0, action: "rewind to checkpoint c2 (after search)" },
    { focus: 1, action: "fork a new branch from c2" },
    { focus: 1, action: "edit prompt: 'be more detailed'" },
    { focus: 1, action: "re-run respond on the new branch" },
    { focus: 1, action: "answer: better — keep this branch" },
  ];
  const { step, containerRef } = useStepper({ steps: STEPS.length, intervalMs: 1500 });
  const cur = STEPS[step];

  return (
    <div ref={containerRef}>
      <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 8, padding: 16 }}>
        <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 11, color: "#6b6b66", marginBottom: 12, textTransform: "uppercase", letterSpacing: "0.06em" }}>thread "t_8a3f" · checkpoints</div>
        <svg viewBox="0 0 600 200" style={{ width: "100%" }}>
          {/* Original branch (top) */}
          <line x1={50} y1={70} x2={550} y2={70} stroke={cur.focus === 0 ? "#2d5fb8" : "#c7c7c0"} strokeWidth="2" />
          {TIMELINE.map((c, i) => {
            const x = 80 + i * 170;
            const isC3 = i === 2;
            return (
              <g key={c.id}>
                <circle cx={x} cy={70} r="14"
                  fill={isC3 && cur.focus === 0 ? "#fbeadc" : "#fff"}
                  stroke={cur.focus === 0 ? "#2d5fb8" : "#c7c7c0"} strokeWidth="2" />
                <text x={x} y={74} textAnchor="middle" fontSize="10" fontFamily="JetBrains Mono, monospace" fill={cur.focus === 0 ? "#2d5fb8" : "#a3a39d"} fontWeight="600">{c.id}</text>
                <text x={x} y={48} textAnchor="middle" fontSize="10" fontFamily="JetBrains Mono, monospace" fill="#1a1a1a">{c.node}</text>
                <text x={x} y={94} textAnchor="middle" fontSize="9" fontFamily="JetBrains Mono, monospace" fill="#a3a39d">{c.time}</text>
              </g>
            );
          })}
          {/* Fork at c2 */}
          {step >= 2 && (
            <>
              <path d="M 250 84 Q 280 130 310 150" fill="none" stroke="#c7521c" strokeWidth="2" strokeDasharray={step >= 4 ? "0" : "3 3"} />
              <line x1={310} y1={150} x2={550} y2={150} stroke="#c7521c" strokeWidth="2" />
              <circle cx={420} cy={150} r="14"
                fill={step >= 5 ? "#e3f1e8" : "#fbeadc"}
                stroke={step >= 5 ? "#2e7d4f" : "#c7521c"} strokeWidth="2" />
              <text x={420} y={154} textAnchor="middle" fontSize="10" fontFamily="JetBrains Mono, monospace" fill={step >= 5 ? "#2e7d4f" : "#c7521c"} fontWeight="600">c3'</text>
              <text x={420} y={134} textAnchor="middle" fontSize="10" fontFamily="JetBrains Mono, monospace" fill="#1a1a1a">respond v2</text>
              <text x={420} y={177} textAnchor="middle" fontSize="9" fontFamily="JetBrains Mono, monospace" fill="#a3a39d">+0.0s · forked</text>
            </>
          )}
          {/* Rewind marker */}
          {step >= 1 && (
            <text x={250} y={28} textAnchor="middle" fontSize="11" fontFamily="JetBrains Mono, monospace" fill="#c7521c" fontWeight="600">↶ rewind here</text>
          )}
        </svg>
      </div>
      <div style={{ marginTop: 12, padding: "10px 14px", background: "#fff", border: "1px solid #e7e7e2", borderRadius: 6, fontSize: 13 }}>
        <span style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 11, color: "#6b6b66", marginRight: 8 }}>step {step+1}/{STEPS.length}:</span>
        {cur.action}
      </div>
    </div>
  );
};

/* ===== Map-Reduce parallel processing ===== */
const MapReduceSim = () => {
  const ITEMS = [
    { id: "doc1", text: "Q1 earnings exceeded guidance.", sentiment: null },
    { id: "doc2", text: "Recall affecting 12% of units.",  sentiment: null },
    { id: "doc3", text: "New CEO praised by analysts.",    sentiment: null },
    { id: "doc4", text: "Layoffs across 4 regions.",       sentiment: null },
    { id: "doc5", text: "Partnership with major retailer.", sentiment: null },
    { id: "doc6", text: "Patent dispute filed.",            sentiment: null },
  ];
  const RESULTS = ["positive","negative","positive","negative","positive","negative"];
  // Phases: 0=split, 1-3=parallel processing in 3 waves, 4=reduce
  const STEPS = 6;
  const { step, containerRef } = useStepper({ steps: STEPS, intervalMs: 1100 });

  // Each doc starts processing in step >=1, completes 1 step later
  const docState = (i) => {
    if (step === 0) return "queued";
    if (step >= 4) return "done";
    if (step >= 2) return "done";
    return i < 3 ? "processing" : "queued";
  };
  // Simpler: docs 0,1 done by step 2; 2,3 done by step 3; 4,5 done by step 4
  const completed = (i) => {
    if (i < 2) return step >= 2;
    if (i < 4) return step >= 3;
    return step >= 4;
  };

  const reduceVisible = step >= 5;

  return (
    <div ref={containerRef}>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 16 }}>
        {/* Map: input docs */}
        <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 8, padding: 14 }}>
          <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 10, color: "#6b6b66", marginBottom: 10, textTransform: "uppercase", letterSpacing: "0.06em" }}>input · 6 docs</div>
          {ITEMS.map((d, i) => (
            <div key={i} style={{
              padding: "8px 10px", marginBottom: 4,
              background: "#fbfbfa", border: "1px solid #e7e7e2",
              borderRadius: 4, fontSize: 11, fontFamily: "JetBrains Mono, monospace",
              opacity: completed(i) ? 0.4 : 1, transition: "opacity 0.3s",
            }}>
              <div style={{ color: "#1a1a1a", fontWeight: 600 }}>{d.id}</div>
              <div style={{ color: "#6b6b66", fontFamily: "Inter Tight, sans-serif", fontSize: 11, marginTop: 2 }}>{d.text}</div>
            </div>
          ))}
        </div>

        {/* Map: parallel workers */}
        <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 8, padding: 14 }}>
          <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 10, color: "#6b6b66", marginBottom: 10, textTransform: "uppercase", letterSpacing: "0.06em" }}>map · classify_sentiment · async</div>
          {ITEMS.map((d, i) => {
            const done = completed(i);
            const inFlight = step >= 1 && !done;
            return (
              <div key={i} style={{
                padding: "8px 10px", marginBottom: 4,
                background: done ? "#e3f1e8" : inFlight ? "#fff" : "#fbfbfa",
                border: `1px solid ${done ? "#b8dcc4" : inFlight ? "#c5d8f5" : "#e7e7e2"}`,
                borderRadius: 4, fontSize: 11, fontFamily: "JetBrains Mono, monospace",
                color: done ? "#2e7d4f" : inFlight ? "#2d5fb8" : "#a3a39d",
                transition: "all 0.3s",
                display: "flex", justifyContent: "space-between",
              }}>
                <span>{d.id} → sentiment</span>
                <span>{done ? `✓ ${RESULTS[i]}` : inFlight ? "⟳ ..." : "queued"}</span>
              </div>
            );
          })}
        </div>

        {/* Reduce */}
        <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 8, padding: 14 }}>
          <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 10, color: "#6b6b66", marginBottom: 10, textTransform: "uppercase", letterSpacing: "0.06em" }}>reduce · aggregate</div>
          {reduceVisible ? (
            <div style={{ animation: "fadeIn 0.5s" }}>
              <div style={{ padding: "12px 14px", background: "#e3f1e8", border: "1px solid #b8dcc4", borderRadius: 6, marginBottom: 8 }}>
                <div style={{ fontSize: 11, fontFamily: "JetBrains Mono, monospace", color: "#2e7d4f", marginBottom: 4 }}>positive: 3</div>
                <div style={{ height: 6, background: "#fff", borderRadius: 2 }}><div style={{ height: "100%", width: "50%", background: "#2e7d4f", borderRadius: 2 }}></div></div>
              </div>
              <div style={{ padding: "12px 14px", background: "#fbeadc", border: "1px solid #ecd690", borderRadius: 6 }}>
                <div style={{ fontSize: 11, fontFamily: "JetBrains Mono, monospace", color: "#c7521c", marginBottom: 4 }}>negative: 3</div>
                <div style={{ height: 6, background: "#fff", borderRadius: 2 }}><div style={{ height: "100%", width: "50%", background: "#c7521c", borderRadius: 2 }}></div></div>
              </div>
              <div style={{ marginTop: 12, fontSize: 12, color: "#6b6b66", textAlign: "center", fontStyle: "italic" }}>
                6 docs in 1.4s · serial would take 6×
              </div>
            </div>
          ) : (
            <div style={{ color: "#a3a39d", fontStyle: "italic", fontSize: 12, padding: 12 }}>— awaiting all map results —</div>
          )}
        </div>
      </div>
      <div style={{ marginTop: 12, fontSize: 11, color: "#6b6b66", textAlign: "center", fontFamily: "JetBrains Mono, monospace" }}>
        graph.add_node("classify", classify_sentiment, fan_out=Send)
      </div>
    </div>
  );
};

/* ===== Async / concurrency · ainvoke + asyncio.gather ===== */
const AsyncSim = () => {
  const [mode, setMode] = useState("async"); // 'sync' or 'async'
  const TASKS = [
    { name: "fetch_user", dur: 800 },
    { name: "fetch_orders", dur: 1100 },
    { name: "fetch_recommendations", dur: 1300 },
  ];
  const TOTAL_SYNC = TASKS.reduce((a, t) => a + t.dur, 0);
  const TOTAL_ASYNC = Math.max(...TASKS.map(t => t.dur));

  const [progress, setProgress] = useState(0);
  const [running, setRunning] = useState(false);

  const run = () => {
    if (running) return;
    setRunning(true);
    setProgress(0);
    const start = Date.now();
    const total = mode === "sync" ? TOTAL_SYNC : TOTAL_ASYNC;
    const tick = () => {
      const elapsed = Date.now() - start;
      const p = Math.min(elapsed / total, 1);
      setProgress(p);
      if (p < 1) requestAnimationFrame(tick);
      else setRunning(false);
    };
    tick();
  };

  return (
    <div>
      <div style={{ display: "flex", gap: 8, marginBottom: 16, alignItems: "center" }}>
        <button onClick={() => { setMode("sync"); setProgress(0); }} style={{
          padding: "6px 14px", borderRadius: 4,
          border: "1px solid", borderColor: mode === "sync" ? "#1a1a1a" : "#e7e7e2",
          background: mode === "sync" ? "#1a1a1a" : "#fff", color: mode === "sync" ? "#fff" : "#3d3d3a",
          fontSize: 12, fontFamily: "Inter Tight, sans-serif", cursor: "pointer", fontWeight: 600,
        }}>sync · invoke()</button>
        <button onClick={() => { setMode("async"); setProgress(0); }} style={{
          padding: "6px 14px", borderRadius: 4,
          border: "1px solid", borderColor: mode === "async" ? "#1a1a1a" : "#e7e7e2",
          background: mode === "async" ? "#1a1a1a" : "#fff", color: mode === "async" ? "#fff" : "#3d3d3a",
          fontSize: 12, fontFamily: "Inter Tight, sans-serif", cursor: "pointer", fontWeight: 600,
        }}>async · asyncio.gather(...)</button>
        <button onClick={run} disabled={running} style={{
          padding: "6px 14px", borderRadius: 4,
          border: "1px solid #2d5fb8", background: running ? "#fbfbfa" : "#2d5fb8",
          color: running ? "#a3a39d" : "#fff",
          fontSize: 12, fontFamily: "Inter Tight, sans-serif", cursor: running ? "not-allowed" : "pointer", fontWeight: 600,
          marginLeft: "auto",
        }}>{running ? "running…" : "▶ run"}</button>
      </div>
      <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 8, padding: 16 }}>
        {TASKS.map((t, i) => {
          const offset = mode === "sync" ? TASKS.slice(0, i).reduce((a, x) => a + x.dur, 0) : 0;
          const taskProg = mode === "sync"
            ? Math.max(0, Math.min(1, (progress * TOTAL_SYNC - offset) / t.dur))
            : Math.max(0, Math.min(1, (progress * TOTAL_ASYNC) / t.dur));
          const total = mode === "sync" ? TOTAL_SYNC : TOTAL_ASYNC;
          const widthPct = (t.dur / total) * 100;
          const leftPct = (offset / total) * 100;
          return (
            <div key={i} style={{ display: "grid", gridTemplateColumns: "200px 1fr 80px", gap: 10, alignItems: "center", marginBottom: 8 }}>
              <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 11, color: "#1a1a1a" }}>{t.name}</div>
              <div style={{ position: "relative", height: 22, background: "#f4f4f1", borderRadius: 3 }}>
                <div style={{
                  position: "absolute", left: `${leftPct}%`, width: `${widthPct}%`,
                  height: "100%", background: "#e8f0fe", borderRadius: 3,
                  border: "1px solid #c5d8f5",
                }}></div>
                <div style={{
                  position: "absolute", left: `${leftPct}%`, width: `${widthPct * taskProg}%`,
                  height: "100%", background: "#2d5fb8", borderRadius: 3, transition: "width 0.05s linear",
                }}></div>
              </div>
              <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 10, color: "#6b6b66", textAlign: "right" }}>{t.dur}ms</div>
            </div>
          );
        })}
        <div style={{ marginTop: 14, padding: "10px 12px", background: "#fbfbfa", borderRadius: 4, fontFamily: "JetBrains Mono, monospace", fontSize: 12, color: "#1a1a1a", display: "flex", justifyContent: "space-between" }}>
          <span>total · {mode}:</span>
          <span style={{ color: mode === "async" ? "#2e7d4f" : "#c7521c", fontWeight: 600 }}>
            {mode === "sync" ? `${TOTAL_SYNC}ms` : `${TOTAL_ASYNC}ms`}
            {mode === "async" && <span style={{ color: "#6b6b66", fontWeight: 400, marginLeft: 8 }}>· {((TOTAL_SYNC/TOTAL_ASYNC).toFixed(1))}× faster</span>}
          </span>
        </div>
      </div>
    </div>
  );
};

/* ===== Computer-use & code-execution agents ===== */
const ComputerUseSim = () => {
  const TRACE = [
    { kind: "goal",    text: "Find the cheapest direct flight SFO → JFK next Friday." },
    { kind: "screenshot", text: "screenshot()", display: "[browser: blank google.com]" },
    { kind: "action",  text: "click(text='Search')" },
    { kind: "type",    text: "type('flights sfo to jfk next friday')" },
    { kind: "screenshot", text: "screenshot()", display: "[results page · flight options visible]" },
    { kind: "code",    text: "extract_prices(html)" },
    { kind: "code-out", text: "[ {airline:'Delta', price:189}, {airline:'JetBlue', price:178}, ... ]" },
    { kind: "answer",  text: "JetBlue $178 — direct, departs 7am Friday." },
  ];
  const { step, containerRef } = useStepper({ steps: TRACE.length, intervalMs: 1300 });
  const KIND_COLOR = {
    goal: "#1a1a1a", screenshot: "#6b3fa0", action: "#c7521c",
    type: "#c7521c", code: "#2d5fb8", "code-out": "#2e7d4f", answer: "#1a1a1a",
  };
  return (
    <div ref={containerRef}>
      <div style={{ background: "#fff", border: "1px solid #e7e7e2", borderRadius: 8, padding: 16, display: "flex", flexDirection: "column", gap: 6 }}>
        {TRACE.slice(0, step + 1).map((t, i) => (
          <div key={i} style={{
            display: "grid", gridTemplateColumns: "110px 1fr",
            gap: 12, padding: "8px 12px",
            background: i === step ? "#fbfbfa" : "transparent",
            border: i === step ? "1px solid #e7e7e2" : "1px solid transparent",
            borderRadius: 4,
            animation: i === step ? "slideIn 0.3s" : undefined,
          }}>
            <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 10, color: KIND_COLOR[t.kind], fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em" }}>{t.kind}</div>
            <div style={{ fontSize: 12, color: "#1a1a1a", fontFamily: "JetBrains Mono, monospace" }}>
              {t.text}
              {t.display && <div style={{ marginTop: 4, padding: "6px 10px", background: "#1a1a1a", color: "#a3a39d", borderRadius: 3, fontSize: 11 }}>{t.display}</div>}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

window.HITLSim = HITLSim;
window.TimeTravelSim = TimeTravelSim;
window.MapReduceSim = MapReduceSim;
window.AsyncSim = AsyncSim;
window.ComputerUseSim = ComputerUseSim;
