// Scene 2: Assistant — Frontier Reasoning (10–22s, 12s duration)
// Rebuilt with spring physics, cadenced typing, per-word reveals,
// signature hero moment on citation hash verification.

function SceneAssistant() {
  const { localTime } = useSprite();
  const t = localTime;

  // Cursor physics path
  const cursorPath = [
    { t: 0.0, x: 960, y: 540 },
    { t: 1.2, x: 960, y: 870 },
    { t: 2.5, x: 1850, y: 870, click: true },
    { t: 8.0, x: 1850, y: 870 },
    { t: 9.8, x: 1020, y: 620 },
    { t: 12.0, x: 1020, y: 620 },
  ];
  const cursor = cursorPhysics(cursorPath, t);

  // Cadenced typing
  const prompt = "Opposing counsel argues the liquidated damages clause is unenforceable as a penalty. Draft a response citing controlling Texas authority.";
  const typedPrompt = typewrite(prompt, t, 0.6, 52);
  const submitted = t > 2.55;

  const steps = [
    { t: 3.0, label: 'Searching 4.4M-node authority graph' },
    { t: 4.3, label: 'Analyzing Clause Genome for penalty doctrine patterns' },
    { t: 5.6, label: 'Cross-referencing Texas Supreme Court holdings' },
    { t: 6.9, label: 'Generating cryptographic evidence pack' },
  ];

  const responseStart = 8.2;
  const citationHoverActive = t > 10.0;

  const cameraStops = [
    { t: 0.0, scale: 1.03, x: 960, y: 820 },
    { t: 1.0, scale: 1.03, x: 960, y: 820 },
    { t: 2.8, scale: 1.0,  x: 960, y: 540 },
    { t: 3.2, scale: 1.05, x: 960, y: 540 },
    { t: 7.5, scale: 1.0,  x: 960, y: 540 },
    { t: 8.5, scale: 1.04, x: 960, y: 500 },
    { t: 10.0, scale: 1.08, x: 960, y: 560 },   // hero push on citation
    { t: 12.0, scale: 1.08, x: 960, y: 560 },
  ];

  return (
    <Camera stops={cameraStops}>
      <AewitaShell activeMode="assistant">
        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column' }}>
          {/* Header */}
          <div style={{
            height: 64, flexShrink: 0,
            borderBottom: `1px solid ${COLORS.border}`,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '0 24px',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <div style={{ fontSize: 20, fontWeight: 600, fontFamily: FONTS.serif }}>Assistant</div>
              <div style={{ fontSize: 12, color: COLORS.textMuted }}>New conversation</div>
            </div>
            <div style={{
              display: 'flex', alignItems: 'center', gap: 8,
              padding: '8px 14px',
              background: COLORS.bgCard,
              border: `1px solid ${COLORS.border}`,
              borderRadius: 8,
              fontSize: 13, color: COLORS.textPrimary,
            }}>
              {Icons.brief}
              <span>Reeves v. Meridian Health</span>
            </div>
          </div>

          {/* Chat body */}
          <div style={{ flex: 1, overflow: 'hidden', padding: '32px 120px', display: 'flex', flexDirection: 'column', gap: 16 }}>
            {/* User bubble — springs in from right */}
            {submitted && (
              <UserBubble t={t} prompt={prompt} />
            )}

            {/* Processing steps with spring check reveals */}
            {submitted && t < responseStart + 0.5 && (
              <ProcessingSteps t={t} steps={steps} fadeAfter={responseStart + 0.2} />
            )}

            {/* Response */}
            {t > responseStart && (
              <ResponseBubble t={t - responseStart} absT={t} citationHoverActive={citationHoverActive} />
            )}
          </div>

          {/* Input bar */}
          <InputBar t={t} typedPrompt={typedPrompt} submitted={submitted} typedLen={typedPrompt.length} fullLen={prompt.length} />
        </div>
      </AewitaShell>
      <Cursor x={cursor.x} y={cursor.y} clicking={cursor.clicking} scale={cursor.scale} />
    </Camera>
  );
}

// User bubble springs in — scale + slide from bottom
function UserBubble({ t, prompt }) {
  const p = spring(t, 0, 1, 2.6, { stiffness: 260, damping: 22 });
  return (
    <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
      <div style={{
        maxWidth: 640,
        padding: '14px 18px',
        background: COLORS.copperDim,
        border: `1px solid ${COLORS.copper}`,
        borderRadius: 14, borderBottomRightRadius: 4,
        fontSize: 14, lineHeight: 1.5,
        color: COLORS.textPrimary,
        opacity: Math.min(1, p),
        transform: `translateY(${(1 - Math.min(1, p)) * 16}px) scale(${0.9 + 0.1 * Math.min(1, p)})`,
        transformOrigin: 'bottom right',
        boxShadow: p > 0.5 ? `0 6px 20px rgba(217,72,78,${0.2 * p})` : 'none',
      }}>
        {prompt}
      </div>
    </div>
  );
}

// Processing steps — each step springs in with rotating spinner,
// checkmark draws on completion
function ProcessingSteps({ t, steps, fadeAfter }) {
  const containerP = spring(t, 0, 1, 2.8, Springs.snappy);
  const fadeOut = t > fadeAfter ? Math.max(0, 1 - spring(t, 0, 1, fadeAfter, { stiffness: 200, damping: 26 })) : 1;
  return (
    <div style={{
      padding: '18px 20px',
      background: COLORS.bgCard,
      border: `1px solid ${COLORS.border}`,
      borderRadius: 12,
      maxWidth: 560,
      display: 'flex', flexDirection: 'column', gap: 12,
      opacity: Math.min(1, containerP) * fadeOut,
      transform: `translateX(${(1 - Math.min(1, containerP)) * -16}px)`,
    }}>
      {steps.map((s, i) => {
        const enterP = spring(t, 0, 1, s.t, { stiffness: 300, damping: 22 });
        const complete = t > s.t + 1.1;
        const checkDraw = clampN(spring(t, 0, 1, s.t + 1.1, { stiffness: 220, damping: 20 }), 0, 1);
        return (
          <div key={i} style={{
            display: 'flex', alignItems: 'center', gap: 12,
            opacity: Math.min(1, enterP) * 0.25 + (complete ? 0.75 : Math.min(1, enterP) * 0.75),
            transform: `translateY(${(1 - Math.min(1, enterP)) * 8}px)`,
          }}>
            <div style={{
              width: 20, height: 20, borderRadius: 10,
              background: complete ? 'rgba(120,179,124,0.15)' : 'rgba(200,133,107,0.15)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: complete ? COLORS.sage : COLORS.copper,
              flexShrink: 0,
              transform: `scale(${complete ? 0.9 + 0.1 * checkDraw : 1})`,
            }}>
              {complete ? (
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
                  <path d="M2.5 6.2 L5 8.6 L9.5 3.6"
                        stroke="currentColor" strokeWidth="1.8"
                        strokeLinecap="round" strokeLinejoin="round"
                        strokeDasharray="12" strokeDashoffset={12 - 12 * checkDraw} />
                </svg>
              ) : (
                <div style={{
                  width: 9, height: 9, borderRadius: 4.5,
                  border: `1.5px solid ${COLORS.copper}`,
                  borderTopColor: 'transparent',
                  transform: `rotate(${t * 360}deg)`,
                }}/>
              )}
            </div>
            <div style={{
              fontSize: 13,
              color: complete ? COLORS.textSecondary : COLORS.textPrimary,
              fontFamily: FONTS.mono,
            }}>{s.label}{complete ? '' : '…'}</div>
          </div>
        );
      })}
    </div>
  );
}

function InputBar({ t, typedPrompt, submitted, typedLen, fullLen }) {
  const armed = typedLen > 20 && !submitted;
  const sendP = armed ? 0.95 + 0.05 * Math.sin(t * 6) : 1;
  return (
    <div style={{ flexShrink: 0, padding: '16px 120px 24px' }}>
      <div style={{
        padding: 14,
        background: COLORS.bgCard,
        border: `1px solid ${typedLen > 0 && !submitted ? COLORS.copper : COLORS.border}`,
        borderRadius: 12,
        display: 'flex', alignItems: 'center', gap: 12,
        boxShadow: typedLen > 0 && !submitted ? `0 0 ${20 + 6 * Math.sin(t * 5)}px rgba(217,72,78,0.1)` : 'none',
      }}>
        <div style={{ flex: 1, fontSize: 14, color: COLORS.textPrimary, minHeight: 20 }}>
          {!submitted ? (
            <>
              {typedPrompt}
              {typedLen < fullLen && typedLen > 0 && (
                <span style={{
                  display: 'inline-block', width: 1.5, height: 16,
                  background: COLORS.copper, marginLeft: 2, verticalAlign: 'middle',
                  opacity: Math.sin(t * 8) > 0 ? 1 : 0,
                }}/>
              )}
              {!typedPrompt && <span style={{ color: COLORS.textMuted }}>Ask me to draft, analyze, or research…</span>}
            </>
          ) : (
            <span style={{ color: COLORS.textMuted }}>Ask a follow-up…</span>
          )}
        </div>
        <div style={{
          width: 32, height: 32, borderRadius: 8,
          background: armed ? COLORS.accent : 'rgba(232,224,216,0.08)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: armed ? '#fff' : COLORS.textMuted,
          transform: `scale(${sendP})`,
          boxShadow: armed ? `0 0 20px rgba(217,72,78,0.4)` : 'none',
        }}>
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
            <path d="M7 2v10M3 6l4-4 4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </div>
      </div>
      <div style={{ fontSize: 11, color: COLORS.textMuted, marginTop: 8, textAlign: 'center' }}>
        Grounded in your documents. Citations link back to the library.
      </div>
    </div>
  );
}

// Response bubble — per-WORD reveal for first paragraph (feels like streaming),
// per-PARAGRAPH spring for rest. Citations glow when hovered.
function ResponseBubble({ t, absT, citationHoverActive }) {
  const para1 = 'Under Texas law, a liquidated damages clause is enforceable if the harm was difficult to estimate at contract formation and the stipulated sum is a reasonable forecast of just compensation.';
  const para1Words = para1.split(' ');
  // Reveal words at ~12 wps
  const wordsShown = Math.floor(Math.max(0, t) * 12);

  return (
    <div style={{
      maxWidth: 720,
      padding: '20px 22px',
      background: COLORS.bgRaised,
      border: `1px solid ${COLORS.border}`,
      borderRadius: 14, borderBottomLeftRadius: 4,
      display: 'flex', flexDirection: 'column', gap: 12,
      fontSize: 14, lineHeight: 1.65,
      color: COLORS.textPrimary,
      position: 'relative',
      opacity: Math.min(1, spring(t, 0, 1, 0, Springs.snappy)),
      transform: `translateX(${(1 - Math.min(1, spring(t, 0, 1, 0, Springs.snappy))) * -16}px)`,
    }}>
      {/* Para 1: per-word streaming reveal */}
      <div>
        {para1Words.map((w, i) => {
          const shown = i < wordsShown;
          return (
            <span key={i} style={{
              opacity: shown ? 1 : 0,
              display: 'inline-block',
              transform: shown ? 'translateY(0)' : 'translateY(4px)',
              transition: 'opacity 200ms, transform 200ms',
              marginRight: 4,
            }}>{w}</span>
          );
        })}
        {wordsShown < para1Words.length && (
          <span style={{
            display: 'inline-block', width: 8, height: 14,
            background: COLORS.copper, opacity: 0.8,
            verticalAlign: 'middle', marginLeft: 1,
          }}/>
        )}
      </div>

      {/* Para 2: citation paragraph, springs in after para 1 */}
      <div style={{
        opacity: Math.min(1, spring(t, 0, 1, 1.5, Springs.snappy)),
        transform: `translateY(${(1 - Math.min(1, spring(t, 0, 1, 1.5, Springs.snappy))) * 6}px)`,
      }}>
        The controlling framework comes from <Citation absT={absT} active={citationHoverActive} cite="Phillips v. Phillips, 820 S.W.2d 785 (Tex. 1991)" /> and <Citation absT={absT} cite="FPL Energy v. TXU Portfolio Mgmt., 426 S.W.3d 59 (Tex. 2014)" />, both of which require the challenging party to prove the clause is a penalty.
      </div>

      {/* Para 3 */}
      <div style={{
        opacity: Math.min(1, spring(t, 0, 1, 2.2, Springs.snappy)),
        transform: `translateY(${(1 - Math.min(1, spring(t, 0, 1, 2.2, Springs.snappy))) * 6}px)`,
      }}>
        Apply a two-pronged test: (1) the anticipated damages were difficult to estimate, and (2) the stipulated amount is a reasonable forecast. Courts apply both prongs at the time of contracting, not in hindsight.
      </div>

      {/* HERO MOMENT: Citation popover with hash verification */}
      {citationHoverActive && (
        <CitationHeroPopover absT={absT} />
      )}
    </div>
  );
}

// The signature hero shot — popover springs in, then the hash reveals
// character-by-character, then the green checkmark draws its stroke,
// and a subtle glow pulses.
function CitationHeroPopover({ absT }) {
  const localT = absT - 10.0;
  const enterP = spring(localT, 0, 1, 0, { stiffness: 220, damping: 20 });
  const hashChars = '0x7ea4b9c...f21'.length;
  const hashRevealed = Math.min(hashChars, Math.floor(Math.max(0, localT - 0.5) * 22));
  const hashText = '0x7ea4b9c...f21'.slice(0, hashRevealed);
  const checkDraw = clampN(spring(localT, 0, 1, 1.4, { stiffness: 220, damping: 20 }), 0, 1);
  const glowP = checkDraw > 0.5 ? 0.5 + 0.5 * Math.sin((localT - 1.4) * 3) : 0;

  return (
    <div style={{
      position: 'absolute',
      left: 54, top: 74,
      width: 360,
      padding: 16,
      background: '#1F2226',
      border: `1px solid ${COLORS.borderStrong}`,
      borderRadius: 10,
      boxShadow: `0 20px 40px rgba(0,0,0,0.5), 0 0 ${30 * glowP}px rgba(120,179,124,${0.3 * glowP})`,
      zIndex: 20,
      opacity: Math.min(1, enterP),
      transform: `translateY(${(1 - Math.min(1, enterP)) * -10}px) scale(${0.92 + 0.08 * Math.min(1, enterP)})`,
      transformOrigin: 'top left',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 8 }}>
        <div style={{
          padding: '2px 8px', borderRadius: 10,
          background: 'rgba(120,179,124,0.15)',
          color: COLORS.sage,
          fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase',
        }}>Good Law</div>
        <div style={{ fontSize: 11, color: COLORS.textMuted }}>Tex. Sup. Ct. · 1991</div>
      </div>
      <div style={{ fontSize: 14, fontWeight: 600, color: COLORS.textPrimary, marginBottom: 4 }}>
        Phillips v. Phillips
      </div>
      <div style={{ fontSize: 11, color: COLORS.textSecondary, fontFamily: FONTS.mono, marginBottom: 10 }}>
        820 S.W.2d 785, 788
      </div>
      <div style={{ fontSize: 12, color: COLORS.textSecondary, lineHeight: 1.5, marginBottom: 12 }}>
        "A court must examine the enforceability of a liquidated damages provision at the time of contracting, not with the benefit of hindsight."
      </div>
      <div style={{
        paddingTop: 10,
        borderTop: `1px solid ${COLORS.border}`,
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        fontSize: 10, fontFamily: FONTS.mono, color: COLORS.textMuted,
      }}>
        <span>hash: {hashText}{hashRevealed < hashChars && <span style={{ opacity: Math.sin(absT * 8) > 0 ? 1 : 0 }}>▎</span>}</span>
        {checkDraw > 0 && (
          <span style={{
            color: COLORS.sage,
            display: 'flex', alignItems: 'center', gap: 4,
            textShadow: `0 0 ${8 * glowP}px rgba(120,179,124,${0.6 * glowP})`,
          }}>
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
              <circle cx="6" cy="6" r="5" stroke="currentColor" strokeWidth="1.2"
                      strokeDasharray="31.4" strokeDashoffset={31.4 * (1 - checkDraw)} />
              <path d="M3.5 6 L5.4 7.8 L8.5 4.2"
                    stroke="currentColor" strokeWidth="1.5"
                    strokeLinecap="round" strokeLinejoin="round"
                    strokeDasharray="10" strokeDashoffset={10 * (1 - Math.max(0, (checkDraw - 0.4) / 0.6))} />
            </svg>
            verified
          </span>
        )}
      </div>
    </div>
  );
}

function Citation({ absT, active, cite }) {
  const glow = active ? 0.5 + 0.5 * Math.sin((absT - 10) * 3) : 0;
  return (
    <span style={{
      color: COLORS.copper,
      borderBottom: `1px solid ${COLORS.copper}`,
      padding: '0 1px',
      cursor: 'pointer',
      textShadow: active ? `0 0 ${8 * glow}px rgba(217,72,78,${0.5 * glow})` : 'none',
    }}>{cite}</span>
  );
}

Object.assign(window, { SceneAssistant });
