import { interpolate } from 'remotion';
import { C } from '../lib/colors';
import { softSpring, clampLerp } from '../lib/easings';

// Phase 4 · 90 frames · 3 s
//
// Two-lane architecture diagram. PRIOR VERSIONS:
//   v7: fake "1,200+ developers building" fork counter (pulled)
//   v9: lane-boxes entered staggered, server entered LATE at frame 18 —
//        owner noted "comes from the right not visible at the start"
//
// THIS VERSION (v10):
//   • All seven boxes appear simultaneously at frame 0-6 (no late
//     server arrival).
//   • A guided GLOW TOUR runs in parallel across both lanes — prompt
//     and vault light up first, then AI and encrypted, then code and
//     env, then the server gets its own glow as the convergent arrows
//     reach it. Each box's border pulses indigo for ~14 frames at its
//     turn so the eye reads the data flow without anything needing to
//     pop in or out.
//   • Closing line slides DOWN from above the canvas and lands
//     centred; the diagram fades cleanly to ~0.12 opacity behind it
//     so the closing card sits in clear space, not overlapping.

interface LaneBox {
  id: string;
  label: string;
  detail?: string;
  cx: number;
  /** Local frame at which this box's glow starts. */
  glowAt: number;
}

const LANE_TOP_Y = 360;
const LANE_BOTTOM_Y = 660;

const BOX_W = 200;
const BOX_H = 96;

// Glow tour timing — top + bottom lane advance in parallel so the
// "two paths" narrative is enforced by the animation cadence itself.
const GLOW_DURATION = 16;       // each box stays "hot" this long
const GLOW_STAGGER = 9;          // gap between consecutive boxes inside one lane

const TOP_LANE_BOXES: LaneBox[] = [
  { id: 'prompt', label: 'prompt', detail: 'your sentence',  cx: 260, glowAt: 4 },
  { id: 'ai',     label: 'AI',     detail: 'generates code', cx: 560, glowAt: 4 + GLOW_STAGGER },
  { id: 'code',   label: 'code',   detail: 'typescript',     cx: 860, glowAt: 4 + GLOW_STAGGER * 2 },
];

const BOTTOM_LANE_BOXES: LaneBox[] = [
  { id: 'vault', label: 'vault',     detail: 'AES-256',             cx: 260, glowAt: 4 },
  { id: 'enc',   label: 'encrypted', detail: 'at rest',             cx: 560, glowAt: 4 + GLOW_STAGGER },
  { id: 'envar', label: 'env',       detail: 'injected at runtime', cx: 860, glowAt: 4 + GLOW_STAGGER * 2 },
];

const SERVER_CX = 1480;
const SERVER_CY = 510;
const SERVER_W = 290;
const SERVER_H = 320;
const SERVER_GLOW_AT = 4 + GLOW_STAGGER * 3;  // glow lights up after both lanes' last boxes

// Closing line takes the final ~1.3 s. Diagram fades to a very low
// opacity at this moment so the card has clean space.
const CLOSING_START = 54;

export function DiscoveryScene({ localFrame, fps }: { localFrame: number; fps: number }) {
  // Universal entrance: every visible element shares this fade-in over
  // frames 0–8. No element pops in late.
  const allInOpacity = clampLerp(localFrame, 0, 8);

  // Diagram dim-down as the closing line takes the stage. Drops to
  // 0.12 (still legible behind, no visual fight) by frame CLOSING + 14.
  const diagramDim = 1 - clampLerp(localFrame, CLOSING_START, CLOSING_START + 14) * 0.88;

  const baseAlpha = allInOpacity * diagramDim;

  return (
    <div style={{ position: 'absolute', inset: 0 }}>
      {/* Section caption — fades out as closing card slides in */}
      <SectionCaption localFrame={localFrame} />

      <div style={{ opacity: baseAlpha }}>
        {/* Lane boxes — all appear at frame 0, glow in sequence */}
        {TOP_LANE_BOXES.map((b) => (
          <LaneBoxView key={b.id} box={b} cy={LANE_TOP_Y} localFrame={localFrame} fps={fps} />
        ))}
        {BOTTOM_LANE_BOXES.map((b) => (
          <LaneBoxView key={b.id} box={b} cy={LANE_BOTTOM_Y} localFrame={localFrame} fps={fps} />
        ))}

        {/* Intra-lane arrows draw between adjacent glows */}
        <IntraLaneArrows boxes={TOP_LANE_BOXES} cy={LANE_TOP_Y} localFrame={localFrame} />
        <IntraLaneArrows boxes={BOTTOM_LANE_BOXES} cy={LANE_BOTTOM_Y} localFrame={localFrame} />

        {/* Server connectors converge from both lane endpoints */}
        <ServerConnectors localFrame={localFrame} />

        {/* "no shared node" vertical chip — the visual claim */}
        <NoSharedNodeDivider localFrame={localFrame} />

        {/* Server box — present from frame 0, glows at SERVER_GLOW_AT */}
        <ServerBox localFrame={localFrame} fps={fps} />
      </div>

      {/* Closing line — slides DOWN from above the canvas, lands centred.
          Sits on top of the dimmed diagram with clear space around it. */}
      <ClosingLine localFrame={localFrame} />
    </div>
  );
}

// ---- Sub-components ----

function SectionCaption({ localFrame }: { localFrame: number }) {
  const inT = clampLerp(localFrame, 4, 18);
  const outT = 1 - clampLerp(localFrame, CLOSING_START - 6, CLOSING_START + 8);
  return (
    <div
      style={{
        position: 'absolute',
        top: 130,
        left: 0,
        right: 0,
        textAlign: 'center',
        fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
        fontSize: 16,
        letterSpacing: 5,
        textTransform: 'uppercase',
        color: C.fgSubtle,
        opacity: Math.min(inT, outT),
        transform: `translateY(${interpolate(inT, [0, 1], [6, 0])}px)`,
      }}
    >
      two paths · never cross
    </div>
  );
}

function LaneBoxView({
  box,
  cy,
  localFrame,
  fps,
}: {
  box: LaneBox;
  cy: number;
  localFrame: number;
  fps: number;
}) {
  // Box is visible from frame 0 with a soft entrance.
  const entryT = softSpring(localFrame, fps, 0, 18);
  const entryOpacity = clampLerp(localFrame, 0, 14);
  const scale = interpolate(entryT, [0, 1], [0.92, 1]);

  // Glow ramp — peaks at glowAt + GLOW_DURATION/2, settles after.
  const glowRamp = clampLerp(localFrame, box.glowAt, box.glowAt + 4);
  const glowFade = 1 - clampLerp(localFrame, box.glowAt + GLOW_DURATION - 4, box.glowAt + GLOW_DURATION + 6);
  const glow = Math.min(glowRamp, glowFade);

  // Once "lit", the box keeps a slightly elevated default state — the
  // viewer should be able to read "this one has been visited."
  const visited = localFrame > box.glowAt + GLOW_DURATION ? 0.45 : 0;
  const heat = Math.max(glow, visited);

  // Border colour ramps from accentDim → accent as heat rises.
  const borderColor = heat > 0.05 ? C.accent : C.accentDim;
  const ringIntensity = 0.08 + heat * 0.35;
  const liftPx = -heat * 4;

  return (
    <div
      style={{
        position: 'absolute',
        left: box.cx - BOX_W / 2,
        top: cy - BOX_H / 2 + liftPx,
        width: BOX_W,
        height: BOX_H,
        transform: `scale(${scale})`,
        opacity: entryOpacity,
        backgroundColor: C.bgElevated,
        border: `1.5px solid ${borderColor}`,
        borderRadius: 12,
        boxShadow: `0 0 0 ${4 + heat * 6}px rgba(99,102,241,${ringIntensity}), 0 16px 40px rgba(0,0,0,0.5)`,
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
        padding: '12px 18px',
        gap: 4,
      }}
    >
      <div
        style={{
          fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
          fontSize: 17,
          color: C.fg,
          letterSpacing: 0.2,
        }}
      >
        {box.label}
      </div>
      {box.detail && (
        <div
          style={{
            fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
            fontSize: 11,
            color: C.fgSubtle,
            letterSpacing: 0.8,
            textTransform: 'lowercase',
          }}
        >
          {box.detail}
        </div>
      )}
    </div>
  );
}

function IntraLaneArrows({
  boxes,
  cy,
  localFrame,
}: {
  boxes: LaneBox[];
  cy: number;
  localFrame: number;
}) {
  return (
    <svg
      width={1920}
      height={1080}
      style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}
    >
      <defs>
        <marker
          id={`arrowLane-${cy}`}
          viewBox="0 0 10 10"
          refX="8"
          refY="5"
          markerWidth="6"
          markerHeight="6"
          orient="auto-start-reverse"
        >
          <path d="M 0 0 L 10 5 L 0 10 Z" fill={C.accent} />
        </marker>
      </defs>
      {boxes.slice(0, -1).map((b, i) => {
        const next = boxes[i + 1]!;
        // Arrow draws when the FROM box's glow has started and the TO
        // box is about to glow — visualises the data flow.
        const x1 = b.cx + BOX_W / 2 + 4;
        const x2 = next.cx - BOX_W / 2 - 8;
        const drawStart = b.glowAt + 4;
        const drawEnd = next.glowAt;
        const progress = clampLerp(localFrame, drawStart, drawEnd);
        if (progress < 0.01) return null;
        const segLen = x2 - x1;
        return (
          <line
            key={`${b.id}-${next.id}`}
            x1={x1}
            y1={cy}
            x2={x2}
            y2={cy}
            stroke={C.accent}
            strokeWidth={1.8}
            strokeDasharray={segLen}
            strokeDashoffset={(1 - progress) * segLen}
            opacity={0.92}
            markerEnd={`url(#arrowLane-${cy})`}
          />
        );
      })}
    </svg>
  );
}

function NoSharedNodeDivider({ localFrame }: { localFrame: number }) {
  const reveal = clampLerp(localFrame, 22, 38);
  const fadeOut = 1 - clampLerp(localFrame, CLOSING_START - 4, CLOSING_START + 8);
  const opacity = Math.min(reveal, fadeOut);
  if (opacity < 0.02) return null;

  // Vertical dashed line + chip pinned in the centre between the lanes
  // at the second column of boxes (x ≈ 560).
  const dividerX = 560;
  const dividerTopY = LANE_TOP_Y + BOX_H / 2 + 12;
  const dividerBottomY = LANE_BOTTOM_Y - BOX_H / 2 - 12;
  const chipY = (dividerTopY + dividerBottomY) / 2;

  return (
    <>
      <svg
        width={1920}
        height={1080}
        style={{ position: 'absolute', inset: 0, pointerEvents: 'none', opacity }}
      >
        <line
          x1={dividerX}
          y1={dividerTopY}
          x2={dividerX}
          y2={dividerBottomY}
          stroke={C.fgSubtle}
          strokeWidth={1}
          strokeDasharray="4 5"
          opacity={0.55}
        />
      </svg>
      <div
        style={{
          position: 'absolute',
          left: dividerX,
          top: chipY,
          transform: 'translate(-50%, -50%)',
          opacity,
          fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
          fontSize: 10.5,
          letterSpacing: 2.2,
          textTransform: 'uppercase',
          color: C.fgMuted,
          backgroundColor: C.bg,
          border: `1px solid ${C.borderStrong}`,
          borderRadius: 999,
          padding: '5px 11px',
          whiteSpace: 'nowrap',
          boxShadow: `0 4px 14px rgba(0,0,0,0.4)`,
        }}
      >
        no shared node
      </div>
    </>
  );
}

function ServerConnectors({ localFrame }: { localFrame: number }) {
  // Connectors reveal as each lane's final box reaches its glow.
  const reveal = clampLerp(localFrame, 4 + GLOW_STAGGER * 2 + 4, 4 + GLOW_STAGGER * 3);
  if (reveal < 0.01) return null;

  const codeBox = TOP_LANE_BOXES[TOP_LANE_BOXES.length - 1]!;
  const envBox = BOTTOM_LANE_BOXES[BOTTOM_LANE_BOXES.length - 1]!;

  const fromTopX = codeBox.cx + BOX_W / 2 + 4;
  const fromTopY = LANE_TOP_Y;
  const fromBotX = envBox.cx + BOX_W / 2 + 4;
  const fromBotY = LANE_BOTTOM_Y;

  const toX = SERVER_CX - SERVER_W / 2 - 4;
  const toTopY = SERVER_CY - SERVER_H / 4;
  const toBotY = SERVER_CY + SERVER_H / 4;

  const lenTop = 460;
  const lenBot = 460;

  return (
    <svg width={1920} height={1080} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
      <defs>
        <marker
          id="arrowConverge"
          viewBox="0 0 10 10"
          refX="8"
          refY="5"
          markerWidth="6"
          markerHeight="6"
          orient="auto-start-reverse"
        >
          <path d="M 0 0 L 10 5 L 0 10 Z" fill={C.accent} />
        </marker>
      </defs>
      <path
        d={`M ${fromTopX} ${fromTopY} C ${fromTopX + 220} ${fromTopY}, ${toX - 200} ${toTopY}, ${toX} ${toTopY}`}
        stroke={C.accent}
        strokeWidth={1.8}
        fill="none"
        strokeDasharray={lenTop}
        strokeDashoffset={(1 - reveal) * lenTop}
        opacity={0.92}
        markerEnd="url(#arrowConverge)"
      />
      <path
        d={`M ${fromBotX} ${fromBotY} C ${fromBotX + 220} ${fromBotY}, ${toX - 200} ${toBotY}, ${toX} ${toBotY}`}
        stroke={C.accent}
        strokeWidth={1.8}
        fill="none"
        strokeDasharray={lenBot}
        strokeDashoffset={(1 - reveal) * lenBot}
        opacity={0.92}
        markerEnd="url(#arrowConverge)"
      />
    </svg>
  );
}

function ServerBox({ localFrame, fps }: { localFrame: number; fps: number }) {
  // Server box is VISIBLE from frame 0 (no late entry) but gets its own
  // glow moment once both lanes have completed their tours.
  const entryT = softSpring(localFrame, fps, 0, 22);
  const entryOpacity = clampLerp(localFrame, 0, 14);
  const scale = interpolate(entryT, [0, 1], [0.9, 1]);

  // Glow ramp at SERVER_GLOW_AT.
  const glowT = clampLerp(localFrame, SERVER_GLOW_AT, SERVER_GLOW_AT + 6);
  const glowDown = clampLerp(localFrame, SERVER_GLOW_AT + 12, SERVER_GLOW_AT + 22);
  const glow = glowT - glowDown;
  const heatBase = localFrame > SERVER_GLOW_AT + 22 ? 0.55 : 0;
  const heat = Math.max(glow, heatBase);

  // Live-pulse on the dot after the glow has landed.
  const pulsePhase = Math.max(0, localFrame - SERVER_GLOW_AT - 4) / 30;
  const pulse = 0.5 + 0.5 * Math.sin(pulsePhase * Math.PI * 2);

  return (
    <div
      style={{
        position: 'absolute',
        left: SERVER_CX - SERVER_W / 2,
        top: SERVER_CY - SERVER_H / 2,
        width: SERVER_W,
        height: SERVER_H,
        transform: `scale(${scale})`,
        transformOrigin: 'center center',
        opacity: entryOpacity,
        backgroundColor: C.bgElevated,
        border: `1.5px solid ${C.accent}`,
        borderRadius: 16,
        boxShadow: `0 0 0 ${5 + heat * 6}px rgba(99,102,241,${0.12 + heat * 0.30}), 0 24px 70px rgba(0,0,0,0.6)`,
        padding: '22px 24px',
        display: 'flex',
        flexDirection: 'column',
        gap: 14,
      }}
    >
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div
          style={{
            fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
            fontSize: 16,
            color: C.fg,
          }}
        >
          your server
        </div>
        <div
          style={{
            display: 'flex',
            alignItems: 'center',
            gap: 6,
            fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
            fontSize: 11,
            letterSpacing: 1.5,
            textTransform: 'uppercase',
            color: C.success,
          }}
        >
          <div
            style={{
              width: 7,
              height: 7,
              borderRadius: 4,
              backgroundColor: C.success,
              boxShadow: `0 0 ${6 + pulse * 10}px ${C.success}`,
              opacity: 0.55 + 0.45 * pulse,
            }}
          />
          live
        </div>
      </div>

      <div
        style={{
          fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
          fontSize: 12,
          color: C.fgSubtle,
          letterSpacing: 1.5,
          textTransform: 'uppercase',
        }}
      >
        receives
      </div>

      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: 8,
          padding: '8px 12px',
          backgroundColor: C.bgSubtle,
          border: `1px solid ${C.border}`,
          borderRadius: 8,
          fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
          fontSize: 13,
          color: C.fg,
        }}
      >
        <span style={{ color: C.fgMuted, fontSize: 11 }}>1.</span>
        <span style={{ color: C.accent, fontSize: 12 }}>‹›</span>
        <span>code</span>
      </div>
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: 8,
          padding: '8px 12px',
          backgroundColor: 'rgba(99,102,241,0.10)',
          border: `1px solid ${C.accentDim}`,
          borderRadius: 8,
          fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
          fontSize: 13,
          color: C.fg,
        }}
      >
        <span style={{ color: C.fgMuted, fontSize: 11 }}>2.</span>
        <SmallLockGlyph />
        <span>env</span>
      </div>
    </div>
  );
}

function SmallLockGlyph() {
  return (
    <svg width="12" height="12" viewBox="0 0 16 16" fill="none">
      <path d="M 5 8 L 5 6 A 3 3 0 0 1 11 6 L 11 8" stroke={C.accent} strokeWidth={1.4} fill="none" />
      <rect x="3.5" y="7.5" width="9" height="7" rx="1.5" fill="rgba(99,102,241,0.20)" stroke={C.accent} strokeWidth={1.4} />
      <circle cx="8" cy="11" r="1" fill={C.accent} />
    </svg>
  );
}

function ClosingLine({ localFrame }: { localFrame: number }) {
  const reveal = clampLerp(localFrame, CLOSING_START, CLOSING_START + 16);
  if (reveal < 0.01) return null;
  // Slides DOWN from above (translateY = -180 → 0) with spring-like
  // ease, lands centred at canvas vertical centre. No overlap with the
  // (now-dimmed) diagram below.
  const slideY = interpolate(reveal, [0, 1], [-180, 0]);
  const scale = interpolate(reveal, [0, 1], [0.94, 1]);
  return (
    <div
      style={{
        position: 'absolute',
        inset: 0,
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        opacity: reveal,
        pointerEvents: 'none',
      }}
    >
      <div
        style={{
          backgroundColor: 'rgba(10,10,11,0.92)',
          backdropFilter: 'blur(6px)',
          border: `1px solid ${C.borderStrong}`,
          borderRadius: 16,
          padding: '30px 60px',
          fontFamily: 'ui-monospace, SF Mono, Menlo, monospace',
          fontSize: 38,
          color: C.fg,
          letterSpacing: 0.5,
          textAlign: 'center',
          transform: `translateY(${slideY}px) scale(${scale})`,
          boxShadow: `0 0 0 6px ${C.accentGlow}, 0 30px 80px rgba(0,0,0,0.65)`,
        }}
      >
        One sentence in. <span style={{ color: C.accent }}>Live server out.</span>
      </div>
    </div>
  );
}
