// scenes-1.jsx — Act I: Tools (Hook, What is a tool, Tool-call round-trip)

// ── shared little components for these scenes ────────────────────────────────
function Bubble({ x, y, w, text, color = COLORS.ink, accent = COLORS.inkFaint, o = 1, tail = 'left', mono = false, align = 'left' }) {
  return (
    <div style={{
      position: 'absolute', left: x, top: y, width: w,
      transform: `translate(-50%,-50%) scale(${0.96 + 0.04 * o})`, opacity: o,
      background: COLORS.bgPanel, border: `1.5px solid ${accent}`,
      borderRadius: 18, padding: '20px 26px',
      fontFamily: mono ? FONTS.mono : FONTS.sans,
      fontSize: mono ? 23 : 30, color, lineHeight: 1.35, textAlign: align,
      boxShadow: '0 14px 40px rgba(0,0,0,0.45)',
    }}>
      {text}
      <span style={{
        position: 'absolute', bottom: -10, [tail]: 38,
        width: 20, height: 20, background: COLORS.bgPanel,
        borderRight: `1.5px solid ${accent}`, borderBottom: `1.5px solid ${accent}`,
        transform: 'rotate(45deg)',
      }} />
    </div>
  );
}

function JsonCard({ x, y, lines, color = COLORS.yellow, o = 1, scale = 1, title = 'tool_call' }) {
  return (
    <div style={{
      position: 'absolute', left: x, top: y, opacity: o,
      transform: `translate(-50%,-50%) scale(${scale})`,
      background: '#0a0d16', border: `1.5px solid ${color}`,
      borderRadius: 14, padding: '14px 18px', minWidth: 330,
      boxShadow: `0 0 30px ${color}33, 0 14px 36px rgba(0,0,0,0.5)`,
      fontFamily: FONTS.mono, fontSize: 21, lineHeight: 1.5,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
        <span style={{ width: 11, height: 11, borderRadius: '50%', background: color }} />
        <span style={{ color: COLORS.inkDim, fontSize: 15, letterSpacing: '0.12em', textTransform: 'uppercase' }}>{title}</span>
      </div>
      {lines.map((ln, i) => (
        <div key={i} style={{ color: ln.c || COLORS.ink, paddingLeft: (ln.indent || 0) * 22, whiteSpace: 'pre' }}>{ln.t}</div>
      ))}
    </div>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// SCENE 1 — HOOK  (length 9s)
// ════════════════════════════════════════════════════════════════════════════
function SceneHook() {
  const { localTime: lt } = useSprite();
  const cx = 960, cy = 520;
  const nodeIn = ramp(lt, 0.2, 1.2, Easing.easeOutBack);
  const titleO = pulse(lt, 1.1, 9, 0.5);

  // three orbiting concepts foreshadowed
  const orbits = [
    { lbl: 'TOOLS',  col: COLORS.yellow, ang: -150, in: 3.0 },
    { lbl: 'MEMORY', col: COLORS.purple, ang: -30,  in: 3.4 },
    { lbl: 'COST',   col: COLORS.coral,  ang: 90,   in: 3.8 },
  ];
  const R = 300;

  return (
    <>
      <Bg accent={COLORS.blue} />
      {orbits.map((o, i) => {
        const oi = ramp(lt, o.in, o.in + 0.9, Easing.easeOutBack);
        const ox = cx + Math.cos(o.ang * Math.PI / 180) * R;
        const oy = cy + Math.sin(o.ang * Math.PI / 180) * R;
        const breath = 1 + Math.sin(lt * 1.4 + i) * 0.015;
        return (
          <React.Fragment key={i}>
            <Wire from={[cx, cy]} to={[ox, oy]} color={o.col + '55'} draw={oi} width={2} />
            <div style={{
              position: 'absolute', left: ox, top: oy, opacity: oi,
              transform: `translate(-50%,-50%) scale(${oi * breath})`,
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
            }}>
              <div style={{ width: 18, height: 18, borderRadius: '50%', background: o.col, boxShadow: `0 0 20px ${o.col}` }} />
              <span style={{ fontFamily: FONTS.mono, fontSize: 21, letterSpacing: '0.16em', color: o.col }}>{o.lbl}</span>
            </div>
          </React.Fragment>
        );
      })}
      <ModelNode x={cx} y={cy} r={92} scale={nodeIn} glow={nodeIn} thinking={lt} />

      <div style={{
        position: 'absolute', left: '50%', top: 118, transform: 'translateX(-50%)',
        opacity: titleO, textAlign: 'center', width: 1400,
      }}>
        <div style={{ fontFamily: FONTS.sans, fontSize: 76, fontWeight: 700, color: COLORS.ink, letterSpacing: '-0.02em', lineHeight: 1.05 }}>
          Agents, Tools &amp; the Cost of Thinking
        </div>
        <div style={{ fontFamily: FONTS.math, fontSize: 34, fontStyle: 'italic', color: COLORS.inkDim, marginTop: 14 }}>
          what an AI agent really does — and what you pay for
        </div>
      </div>
    </>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// SCENE 2 — WHAT IS A TOOL  (length 17s)
// ════════════════════════════════════════════════════════════════════════════
function SceneWhatTool() {
  const { localTime: lt } = useSprite();
  const mx = 560, my = 560;

  const nodeIn = ramp(lt, 0.2, 1.0, Easing.easeOutBack);
  const qIn = pulse(lt, 1.2, 7.6, 0.45);
  const stuckIn = pulse(lt, 3.4, 7.6, 0.4);
  // tool slides in
  const toolIn = ramp(lt, 8.2, 9.2, Easing.easeOutBack);
  const wireDraw = ramp(lt, 9.4, 10.4);
  const tx = 1390, ty = 560;

  return (
    <>
      <Bg accent={COLORS.yellow} />
      <Eyebrow lt={lt} a={0.4} b={17} n="01" label="What is a tool?" color={COLORS.yellow} />

      <ModelNode x={mx} y={my} r={88} scale={nodeIn} glow={nodeIn} thinking={lt < 7.8 ? lt : 0} />

      {/* user question */}
      <Bubble x={mx} y={my - 250} w={520} o={qIn}
        text={<span><span style={{color: COLORS.inkDim}}>user ·</span> "What's the weather in Tokyo <i>right now</i>?"</span>} />

      {/* stuck indicator over the model */}
      {stuckIn > 0.01 && (
        <div style={{
          position: 'absolute', left: mx + 70, top: my - 86, opacity: stuckIn,
          transform: `scale(${0.7 + stuckIn * 0.3})`,
          width: 56, height: 56, borderRadius: '50%',
          background: COLORS.coral, color: '#0c0e14',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontFamily: FONTS.math, fontSize: 40, fontWeight: 700,
          boxShadow: `0 0 26px ${COLORS.coral}`,
        }}>?</div>
      )}

      {/* the tool */}
      {toolIn > 0.01 && (
        <>
          <Wire from={[mx + 96, my]} to={[tx - 160, ty]} color={COLORS.yellow} draw={wireDraw} dashed width={3} />
          <ToolBox x={tx} y={ty} w={330} scale={toolIn} active={1}
            sig="get_weather(city)" desc="calls a live weather API" />
        </>
      )}

      <Caption lt={lt} a={3.6} b={7.8} color={COLORS.coral}>
        A model's knowledge is <b>frozen</b> — it can't see anything live.
      </Caption>
      <Caption lt={lt} a={9.4} b={13.2}>
        A <b style={{color: COLORS.yellow}}>tool</b> is just a function the model is allowed to call.
      </Caption>
      <Caption lt={lt} a={13.4} b={17}>
        Weather, search, code, databases — anything you can wrap in a function.
      </Caption>
    </>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// SCENE 3 — TOOL-CALL ROUND TRIP  (length 22s)
// ════════════════════════════════════════════════════════════════════════════
function SceneToolCall() {
  const { localTime: lt } = useSprite();
  const mx = 470, my = 540, tx = 1450, ty = 540;
  const midY = 540;

  // beats
  const setup    = ramp(lt, 0.2, 1.0, Easing.easeOutCubic);
  // 1) request travels model -> tool  (2.2 .. 4.6)
  const reqTravel = ramp(lt, 2.2, 4.4, Easing.easeInOutCubic);
  const reqVisible = pulse(lt, 2.0, 5.2, 0.4);
  // 2) tool executes (5.0 .. 7.0)
  const exec = pulse(lt, 5.0, 7.4, 0.4);
  // 3) result travels tool -> model (7.4 .. 9.6)
  const resTravel = ramp(lt, 7.6, 9.8, Easing.easeInOutCubic);
  const resVisible = pulse(lt, 7.4, 10.8, 0.4);
  // 4) answer (11 .. end)
  const ansIn = pulse(lt, 11.4, 22, 0.45);

  const reqX = mx + 110 + (tx - 200 - (mx + 110)) * reqTravel;
  const resX = tx - 200 + ((mx + 110) - (tx - 200)) * resTravel;

  const toolActive = exec > 0.3 || reqTravel > 0.9 ? 1 : 0.0;

  return (
    <>
      <Bg accent={COLORS.blue} />
      <Eyebrow lt={lt} a={0.4} b={22} n="02" label="Calling a tool" color={COLORS.blue} />

      <ModelNode x={mx} y={my} r={84} scale={setup} glow={setup}
        thinking={(lt > 0.6 && lt < 2.2) || (lt > 9.8 && lt < 11.6) ? lt : 0} />
      <div style={{ position: 'absolute', left: mx, top: my + 116, transform: 'translateX(-50%)', opacity: setup, fontFamily: FONTS.sans, fontSize: 22, color: COLORS.inkDim }}>the model</div>

      <ToolBox x={tx} y={ty} w={330} scale={setup} active={toolActive}
        sig="get_weather(city)" desc="runs in your code" icon={exec > 0.3 ? '↻' : '⚙'} />

      {/* base wire */}
      <Wire from={[mx + 96, midY]} to={[tx - 180, midY]} color={COLORS.inkFaint + '88'} draw={setup} width={2} dashed />

      {/* 1. request card travelling right */}
      {reqVisible > 0.01 && (
        <JsonCard x={reqX} y={midY - 150} o={reqVisible} title="model → request"
          color={COLORS.yellow}
          lines={[
            { t: '{', c: COLORS.inkDim },
            { t: '"name": "get_weather",', c: COLORS.yellow, indent: 1 },
            { t: '"args": { "city": "Tokyo" }', c: COLORS.ink, indent: 1 },
            { t: '}', c: COLORS.inkDim },
          ]} />
      )}

      {/* execution flash on tool */}
      {exec > 0.02 && (
        <div style={{
          position: 'absolute', left: tx, top: ty - 150, transform: 'translate(-50%,-50%)',
          opacity: exec, fontFamily: FONTS.mono, fontSize: 20, color: COLORS.green,
          display: 'flex', alignItems: 'center', gap: 10,
        }}>
          <span style={{ width: 12, height: 12, borderRadius: '50%', background: COLORS.green, boxShadow: `0 0 14px ${COLORS.green}` }} />
          executing… fetch api.weather.com
        </div>
      )}

      {/* 3. result card travelling left */}
      {resVisible > 0.01 && (
        <JsonCard x={resX} y={midY + 165} o={resVisible} title="tool → result"
          color={COLORS.green}
          lines={[
            { t: '{', c: COLORS.inkDim },
            { t: '"temp_c": 18,', c: COLORS.green, indent: 1 },
            { t: '"sky": "clear"', c: COLORS.ink, indent: 1 },
            { t: '}', c: COLORS.inkDim },
          ]} />
      )}

      {/* 4. final answer */}
      {ansIn > 0.01 && (
        <Bubble x={mx + 40} y={my - 250} w={560} o={ansIn} accent={COLORS.blue}
          text={<span><span style={{color: COLORS.blue}}>assistant ·</span> "It's <b>18°C and clear</b> in Tokyo right now."</span>} />
      )}

      <Caption lt={lt} a={2.4} b={5.0}>
        The model doesn't run anything — it writes a <b style={{color: COLORS.yellow}}>structured request</b>.
      </Caption>
      <Caption lt={lt} a={5.4} b={7.6} color={COLORS.green}>
        <b>Your</b> code runs the function and hands back the result.
      </Caption>
      <Caption lt={lt} a={8.0} b={11.2}>
        That result is fed back in as new context…
      </Caption>
      <Caption lt={lt} a={11.8} b={22}>
        …and the model folds it into a real answer.
      </Caption>
    </>
  );
}

Object.assign(window, { SceneHook, SceneWhatTool, SceneToolCall, Bubble, JsonCard });
