import { useCurrentFrame, useVideoConfig, interpolate } from 'remotion';
import { C } from '../lib/colors';
import { rand, clampLerp, easeInOut, softSpring } from '../lib/easings';
import { BEAT } from '../HeroVideo';

// Beat 2 — the wow moment.
//
// The prompt words detonate into ~30 particle dots. Each particle has
// (a) a random scatter velocity that decays, (b) a magnetic pull toward
// a designated target slot on the SERVER SCHEMATIC that materialises in
// the centre. As particles arrive, the schematic strokes itself on
// line-by-line. A scan-line sweeps over the formed server right before
// it settles.

const PARTICLE_COUNT = 36;

// Target slots on the server schematic — points on the rectangle's
// perimeter plus internal "row" markers. Particles slot into these.
const SERVER_W = 460;
const SERVER_H = 300;
const CX = 960;
const CY = 540;

function targetSlot(i: number) {
  const N = PARTICLE_COUNT;
  // Distribute slots: half on the perimeter, half on internal "tool rows".
  if (i < N / 2) {
    // perimeter — walk around the rectangle
    const t = i / (N / 2);
    const perim = 2 * (SERVER_W + SERVER_H);
    const d = t * perim;
    const left = CX - SERVER_W / 2;
    const top = CY - SERVER_H / 2;
    let px = left;
    let py = top;
    if (d < SERVER_W) {
      px = left + d;
      py = top;
    } else if (d < SERVER_W + SERVER_H) {
      px = left + SERVER_W;
      py = top + (d - SERVER_W);
    } else if (d < 2 * SERVER_W + SERVER_H) {
      px = left + SERVER_W - (d - SERVER_W - SERVER_H);
      py = top + SERVER_H;
    } else {
      px = left;
      py = top + SERVER_H - (d - 2 * SERVER_W - SERVER_H);
    }
    return { x: px, y: py };
  }
  // Internal tool rows — three horizontal lines inside the server
  const j = i - N / 2;
  const row = j % 3;
  const col = Math.floor(j / 3) / (N / 2 / 3 - 1);
  const rowY = CY - 60 + row * 60;
  const rowX = CX - SERVER_W / 2 + 30 + col * (SERVER_W - 60);
  return { x: rowX, y: rowY };
}

export function TransformScene() {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  // Local frame within the beat — frame 0 is the start of Transform.
  const local = frame - BEAT.transform.in; // 0..110
  const total = BEAT.transform.out - BEAT.transform.in;

  // Entrance + exit envelopes for the scene as a whole.
  const sceneIn = clampLerp(frame, BEAT.transform.in, BEAT.transform.in + 6);
  const sceneOut = 1 - clampLerp(frame, BEAT.transform.out - 8, BEAT.transform.out);
  const sceneAlpha = Math.min(sceneIn, sceneOut);

  // Schematic stroke-on: 0→1 between frames 35..65 of the beat.
  const strokeT = easeInOut(clampLerp(local, 30, 70));
  // Port pulse readiness — only after schematic strokes complete.
  const portPulse = clampLerp(local, 70, 95);

  // Scan-line sweep — diagonal gradient passes once across the formed server
  const scanT = clampLerp(local, 70, 100);

  return (
    <div style={{ position: 'absolute', inset: 0, opacity: sceneAlpha }}>
      {/* Particles */}
      <svg width={1920} height={1080} style={{ position: 'absolute', inset: 0 }}>
        {Array.from({ length: PARTICLE_COUNT }).map((_, i) => {
          // Source: prompt word approximate position spread across the line
          const wordIndex = i % 4;
          const wordX = 760 + wordIndex * 130 + rand(i * 7.13) * 60 - 30;
          const wordY = 540 + rand(i * 3.71) * 20 - 10;

          // Target slot on server
          const slot = targetSlot(i);

          // Scatter velocity — frames 0..25 the particle drifts outward;
          // then frames 25..60 it pulls toward the target with spring.
          const vx = (rand(i * 1.31) - 0.5) * 600;
          const vy = (rand(i * 2.71) - 0.5) * 400;

          // Phase 1: explosion 0..25
          const explode = clampLerp(local, 0, 25);
          // Phase 2: magnetic pull 25..60
          const pull = softSpring(frame, fps, BEAT.transform.in + 25, 36);

          // Position is: (wordPos) + (vx,vy * explode) lerped toward target by pull
          const driftX = wordX + vx * explode * (1 - pull);
          const driftY = wordY + vy * explode * (1 - pull);
          const x = driftX + (slot.x - driftX) * pull;
          const y = driftY + (slot.y - driftY) * pull;

          // Size grows as particles "lock in"
          const r = interpolate(pull, [0, 1], [2.5, 1.8]);
          // Color shifts from white → indigo as they lock to schematic
          const color = pull > 0.6 ? C.accent : C.fg;
          // Fade in fast at the start so the explosion is visible
          const alpha = clampLerp(local, 0, 4);
          // Slight fade-out near end as the schematic takes visual primacy
          const fadeOut = 1 - clampLerp(local, 85, 105) * 0.3;

          return (
            <circle
              key={i}
              cx={x}
              cy={y}
              r={r}
              fill={color}
              opacity={alpha * fadeOut * 0.95}
              style={{
                filter: pull > 0.5 ? `drop-shadow(0 0 4px ${C.accentGlow})` : undefined,
              }}
            />
          );
        })}
      </svg>

      {/* Server schematic — strokes on as particles arrive */}
      <svg
        width={1920}
        height={1080}
        style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}
      >
        <defs>
          <linearGradient id="scanline" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset={`${Math.max(0, scanT * 100 - 8)}%`} stopColor={C.accent} stopOpacity="0" />
            <stop offset={`${scanT * 100}%`} stopColor={C.accent} stopOpacity="0.85" />
            <stop offset={`${Math.min(100, scanT * 100 + 8)}%`} stopColor={C.accent} stopOpacity="0" />
          </linearGradient>
        </defs>

        {/* Outer rectangle — stroke draws perimeter from top-left clockwise */}
        <rect
          x={CX - SERVER_W / 2}
          y={CY - SERVER_H / 2}
          width={SERVER_W}
          height={SERVER_H}
          rx={6}
          fill="none"
          stroke={C.accent}
          strokeWidth={2}
          strokeDasharray={2 * (SERVER_W + SERVER_H)}
          strokeDashoffset={(1 - strokeT) * 2 * (SERVER_W + SERVER_H)}
          opacity={0.9}
        />

        {/* Three internal "tool" rows — appear after perimeter completes */}
        {[0, 1, 2].map((r) => {
          const rowAlpha = clampLerp(local, 60 + r * 4, 72 + r * 4);
          const y = CY - 60 + r * 60;
          return (
            <g key={r} opacity={rowAlpha}>
              <line
                x1={CX - SERVER_W / 2 + 24}
                y1={y}
                x2={CX + SERVER_W / 2 - 24}
                y2={y}
                stroke={C.borderStrong}
                strokeWidth={1}
              />
              <circle cx={CX - SERVER_W / 2 + 30} cy={y} r={3} fill={C.accent} opacity={0.9} />
            </g>
          );
        })}

        {/* Port dots — 4 each side, pulse once schematic locks in */}
        {[-1, 1].map((side) =>
          [-1, 0, 1].map((off) => (
            <circle
              key={`${side}-${off}`}
              cx={CX + (SERVER_W / 2) * side}
              cy={CY + off * 60}
              r={4}
              fill={C.accent}
              opacity={portPulse * (0.6 + 0.4 * Math.sin(local * 0.3 + off))}
              style={{ filter: `drop-shadow(0 0 6px ${C.accentGlow})` }}
            />
          )),
        )}

        {/* Scan-line sweep — diagonal pass after stroke completes */}
        {scanT > 0 && scanT < 1 && (
          <rect
            x={CX - SERVER_W / 2}
            y={CY - SERVER_H / 2}
            width={SERVER_W}
            height={SERVER_H}
            rx={6}
            fill="url(#scanline)"
            opacity={0.55}
          />
        )}
      </svg>

      {/* Corner labels — typographic detail that sells "this is a real server" */}
      <CornerLabel x={CX - SERVER_W / 2 - 8} y={CY - SERVER_H / 2 - 28} text="mcp-notion" appearAt={local} delay={62} />
      <CornerLabel x={CX + SERVER_W / 2 + 8} y={CY - SERVER_H / 2 - 28} text="OAuth 2.1" appearAt={local} delay={68} align="right" />
      <CornerLabel x={CX - SERVER_W / 2 - 8} y={CY + SERVER_H / 2 + 18} text="search_pages" appearAt={local} delay={72} />
      <CornerLabel x={CX + SERVER_W / 2 + 8} y={CY + SERVER_H / 2 + 18} text="get_page_content" appearAt={local} delay={76} align="right" />
    </div>
  );
}

function CornerLabel({
  x,
  y,
  text,
  appearAt,
  delay,
  align = 'left',
}: {
  x: number;
  y: number;
  text: string;
  appearAt: number;
  delay: number;
  align?: 'left' | 'right';
}) {
  const t = clampLerp(appearAt, delay, delay + 8);
  return (
    <div
      style={{
        position: 'absolute',
        left: align === 'left' ? x : undefined,
        right: align === 'right' ? 1920 - x : undefined,
        top: y,
        fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
        fontSize: 13,
        letterSpacing: '0.06em',
        color: C.fgMuted,
        opacity: t,
        transform: `translateY(${(1 - t) * 4}px)`,
      }}
    >
      {text}
    </div>
  );
}
