// scenes.jsx — cursor snaps to actual DOM button positions via refs.

function FileRowEntry({ name, size, t }) {
  // t is seconds since this row appeared
  const progress = clamp(t / 0.36, 0, 1);
  const eased = Easing.easeOutCubic(progress);
  return (
    <div style={{
      opacity: eased,
      transform: `translateY(${(1 - eased) * 8}px)`,
    }}>
      <FileRow name={name} size={size} />
    </div>
  );
}

// Timing (15s total):
//  0.0 – 4.2s   Scene 1: Upload modal (cursor -> dropzone -> Import button)
//  4.2 – 7.4s   Scene 2: Score reveal at 12%
//  7.4 – 11.0s  Scene 3: Address an issue (cursor -> Upload button on row 1)
//  11.0 – 15.0s Scene 4: Score climb 12% -> 100%

// Measure an element's position relative to a container, so the cursor can
// be placed on it exactly regardless of layout/flex positioning.
function useAnchor(ref, containerRef) {
  const [anchor, setAnchor] = React.useState(null);
  React.useLayoutEffect(() => {
    const measure = () => {
      if (!ref.current || !containerRef.current) return;
      // Use offset-based measurement so scale() transforms don't skew it.
      let el = ref.current;
      let x = 0, y = 0;
      while (el && el !== containerRef.current) {
        x += el.offsetLeft;
        y += el.offsetTop;
        el = el.offsetParent;
      }
      setAnchor({
        x: x + ref.current.offsetWidth  / 2,
        y: y + ref.current.offsetHeight / 2,
      });
    };
    measure();
    // remeasure a few times as fonts/layout settle
    const tids = [50, 150, 400].map(ms => setTimeout(measure, ms));
    window.addEventListener('resize', measure);
    return () => {
      tids.forEach(clearTimeout);
      window.removeEventListener('resize', measure);
    };
  }, []);
  return anchor;
}

// ── Scene 1: Upload modal ──────────────────────────────────────────────────
function SceneUpload() {
  const { localTime: t } = useSprite();

  const file1In = t > 1.2;
  const file2In = t > 2.0;
  const readyCount = (file1In ? 1 : 0) + (file2In ? 1 : 0);
  const primaryActive = readyCount === 2;

  const containerRef = React.useRef(null);
  const dropRef = React.useRef(null);
  const importRef = React.useRef(null);
  const dropPos = useAnchor(dropRef, containerRef);
  const importPos = useAnchor(importRef, containerRef);

  // Default to sensible fallbacks while refs measure
  const drop = dropPos || { x: 410, y: 210 };
  const imp  = importPos || { x: 670, y: 505 };

  // Cursor motion: quick, decisive moves. Two legs — dropzone -> Import.
  // easeOutQuart decelerates fast, so cursor arrives and stabilizes.
  const cursorX = interpolate(
    [0,     0.9,         2.5,   3.2],
    [drop.x + 520, drop.x, drop.x, imp.x],
    [Easing.easeOutQuart, Easing.linear, Easing.easeOutQuart]
  )(t);
  const cursorY = interpolate(
    [0,     0.9,         2.5,   3.2],
    [drop.y + 380, drop.y, drop.y, imp.y],
    [Easing.easeOutQuart, Easing.linear, Easing.easeOutQuart]
  )(t);
  const clicking =
    (t > 1.15 && t < 1.30) ||
    (t > 1.95 && t < 2.10) ||
    (t > 3.30 && t < 3.50);
  const dragActive = t > 0.85 && t < 2.2;

  const entryT = Easing.easeOutCubic(clamp(t / 0.5, 0, 1));
  const exitT = clamp((t - 3.8) / 0.4, 0, 1);

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'rgba(20,20,20,0.22)',
      opacity: entryT * (1 - exitT),
    }}>
      <div
        ref={containerRef}
        style={{
          position: 'relative',
          transform: `scale(${(0.96 + 0.04 * entryT) * (1 - exitT * 0.02)})`,
          transformOrigin: 'center',
        }}
      >
        <ModalShell title="Import Documents" width={820}>
          <TabBar active="upload" />
          <div ref={dropRef}>
            <DropZone dragActive={dragActive} />
          </div>

          <div style={{ padding: '18px 28px 0', minHeight: 140 }}>
            <div style={{
              fontSize: 12, color: BRAND.subtle,
              opacity: readyCount > 0 ? 1 : 0,
              marginBottom: 10,
              transition: 'opacity 200ms',
              fontWeight: 500,
            }}>
              {readyCount} file{readyCount === 1 ? '' : 's'} selected
            </div>

            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {file1In && (
                <FileRowEntry name="company-constitution.pdf" size="277 KB" t={t - 1.2} />
              )}
              {file2In && (
                <FileRowEntry name="company-register-docs.pdf" size="754 KB" t={t - 2.0} />
              )}
            </div>
          </div>

          <ModalFooter
            leftText={`${readyCount} file${readyCount === 1 ? '' : 's'} ready`}
            primaryLabel="Import & Analyze"
            primaryActive={primaryActive}
            primaryRef={importRef}
          />
        </ModalShell>

        <Cursor x={cursorX} y={cursorY} clicking={clicking} opacity={1 - exitT} />
      </div>
    </div>
  );
}

// ── Scene 2: Score reveal at 12% ──────────────────────────────────────────
function SceneScoreReveal() {
  const { localTime: t, duration } = useSprite();

  const countTarget = 12;
  const count = t < 1.2
    ? Easing.easeOutCubic(clamp(t / 1.2, 0, 1)) * countTarget
    : countTarget;

  const entryT = Easing.easeOutCubic(clamp(t / 0.5, 0, 1));
  const exitT = clamp((t - (duration - 0.4)) / 0.4, 0, 1);

  // Camera zoom — start slightly zoomed out, ease in
  const camScale = 1.25 + (1 - entryT) * -0.05;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      gap: 40,
      opacity: entryT * (1 - exitT),
      transform: `translateY(${(1 - entryT) * 14 + exitT * -10}px) scale(${camScale})`,
      transformOrigin: 'center',
    }}>
      <Caption style={{ opacity: t > 0.3 ? 1 : 0, transition: 'opacity 320ms', fontSize: 18 }}>
        Your Legal Coverage
      </Caption>
      <LegalCoverageCard pct={count} width={900} />
      <div style={{
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 18,
        color: BRAND.subtle,
        maxWidth: 640,
        textAlign: 'center',
        opacity: t > 0.9 ? 1 : 0,
        transition: 'opacity 400ms',
      }}>
        Upload more documents to improve your coverage.
      </div>
    </div>
  );
}

// ── Scene 3: Address an issue ─────────────────────────────────────────────
function SceneFix() {
  const { localTime: t, duration } = useSprite();

  const containerRef = React.useRef(null);
  const uploadBtnRef = React.useRef(null);
  const btnPos = useAnchor(uploadBtnRef, containerRef);
  const btn = btnPos || { x: 770, y: 265 };

  // Cursor motion: single decisive arc to the Upload button.
  const cursorX = interpolate(
    [0,     1.6,   3.2],
    [btn.x + 380, btn.x, btn.x],
    [Easing.easeOutQuart, Easing.linear]
  )(t);
  const cursorY = interpolate(
    [0,     1.6,   3.2],
    [btn.y + 280, btn.y, btn.y],
    [Easing.easeOutQuart, Easing.linear]
  )(t);
  const clicking = (t > 1.75 && t < 1.95);
  const uploadHover = t > 1.25;
  const addressed = t > 2.0;
  const showToast = t > 1.9 && t < 3.2;

  const entryT = Easing.easeOutCubic(clamp(t / 0.5, 0, 1));
  const exitT = clamp((t - (duration - 0.4)) / 0.4, 0, 1);
  const camScale = 1.15;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      gap: 24,
      opacity: entryT * (1 - exitT),
      transform: `translateY(${(1 - entryT) * 14}px) scale(${camScale})`,
      transformOrigin: 'center',
    }}>
      <Caption style={{ opacity: t > 0.3 ? 1 : 0, transition: 'opacity 320ms', fontSize: 18 }}>
        Address Flagged Items
      </Caption>
      <div ref={containerRef} style={{ position: 'relative' }}>
        <CategoryCard
          width={1000}
          progressPct={addressed ? 33 : 16}
          highlightUploadId="sgp1"
          uploadHover={uploadHover}
          addressedIds={addressed ? ['sgp1'] : []}
          uploadBtnRef={uploadBtnRef}
        />

        <div style={{
          position: 'absolute',
          bottom: -80,
          right: 0,
          opacity: showToast ? 1 : 0,
          transform: `translateY(${showToast ? 0 : 12}px)`,
          transition: 'opacity 280ms, transform 280ms cubic-bezier(0.2,0.9,0.3,1)',
        }}>
          <UploadToast filename="super-q1-2025.pdf" />
        </div>

        <Cursor x={cursorX} y={cursorY} clicking={clicking} opacity={1 - exitT} />
      </div>
    </div>
  );
}

// ── Scene 4: Climb to 100 ─────────────────────────────────────────────────
function SceneClimb() {
  const { localTime: t, duration } = useSprite();

  const pct = interpolate(
    [0, 0.3, 0.8, 1.2, 1.6, 2.2, 2.8, 3.2, 3.8],
    [12, 28, 34, 52, 60, 78, 88, 96, 100],
    Easing.easeOutCubic
  )(t);

  const entryT = Easing.easeOutCubic(clamp(t / 0.5, 0, 1));
  const celebrate = pct >= 99.5;
  const camScale = 1.25;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center',
      gap: 32,
      opacity: entryT,
      transform: `translateY(${(1 - entryT) * 14}px) scale(${camScale})`,
      transformOrigin: 'center',
    }}>
      <Caption style={{ opacity: t > 0.3 ? 1 : 0, transition: 'opacity 320ms', fontSize: 18 }}>
        Your Score Climbs
      </Caption>
      <div style={{ position: 'relative' }}>
        <LegalCoverageCard pct={pct} width={900} />
        {celebrate && <ConfettiBurst />}
      </div>
      <div style={{
        fontFamily: 'Inter, system-ui, sans-serif',
        fontSize: 34,
        fontWeight: 700,
        letterSpacing: '-0.02em',
        color: BRAND.ink,
        opacity: pct > 95 ? 1 : 0,
        transform: `translateY(${pct > 95 ? 0 : 10}px)`,
        transition: 'opacity 400ms, transform 400ms cubic-bezier(0.2,0.9,0.3,1)',
      }}>
        Legally healthy.
      </div>
    </div>
  );
}

function ConfettiBurst() {
  const dots = React.useMemo(() => {
    const arr = [];
    for (let i = 0; i < 24; i++) {
      const angle = (i / 24) * Math.PI * 2 + Math.random() * 0.3;
      const dist = 70 + Math.random() * 90;
      arr.push({
        id: i,
        x: Math.cos(angle) * dist,
        y: Math.sin(angle) * dist - 10,
        color: [BRAND.green, BRAND.amber, BRAND.indigo, '#FFFFFF'][i % 4],
        size: 5 + Math.random() * 6,
        rot: Math.random() * 180,
        delay: Math.random() * 120,
      });
    }
    return arr;
  }, []);
  return (
    <div style={{
      position: 'absolute',
      left: 60, top: 60,
      pointerEvents: 'none',
    }}>
      {dots.map(d => (
        <div key={d.id} style={{
          position: 'absolute',
          width: d.size, height: d.size,
          background: d.color,
          borderRadius: 2,
          transform: `translate(${d.x}px, ${d.y}px) rotate(${d.rot}deg)`,
          animation: `confettiPop 800ms cubic-bezier(0.2,0.9,0.3,1) both`,
          animationDelay: `${d.delay}ms`,
          opacity: 0.9,
          boxShadow: '0 1px 2px rgba(0,0,0,0.08)',
        }}/>
      ))}
    </div>
  );
}

Object.assign(window, { SceneUpload, SceneScoreReveal, SceneFix, SceneClimb, ConfettiBurst, useAnchor });
