// shared.jsx — primitives reused across scenes

// ── Resolve a "target selector" to a stage-coord {x,y} ──────────────────────
// Each frame, we look up [data-target="<id>"] inside the stage canvas and
// return its center in 1920×1080 coords. This way clicks always land on the
// real button no matter how the layout reflows.
function resolveTarget(sel) {
  if (!sel) return null;
  const el = document.querySelector(`[data-target="${sel}"]`);
  if (!el) return null;
  // Walk up to the scaled canvas ([style*="scale"]); we want coords in its
  // pre-transform space (1920×1080).
  let canvas = el.parentElement;
  while (canvas && !canvas.style.transform?.includes('scale')) canvas = canvas.parentElement;
  if (!canvas) canvas = document.body;
  const cr = canvas.getBoundingClientRect();
  const er = el.getBoundingClientRect();
  // Pre-transform width = 1920; current rendered width = cr.width.
  const sx = 1920 / cr.width;
  const sy = 1080 / cr.height;
  return {
    x: (er.left + er.width / 2 - cr.left) * sx,
    y: (er.top + er.height / 2 - cr.top) * sy,
  };
}

// ── Smooth interpolated cursor with click ripple ───────────────────────────
// Each waypoint can be {t, x, y} OR {t, target:'selector'} — selectors
// resolve every frame against [data-target=...] in the stage.
function Cursor({ path, clicks = [], visible = true, color = '#fff', time: timeProp }) {
  const ctxTime = useTime();
  const time = (typeof timeProp === 'number') ? timeProp : ctxTime;
  const [, force] = React.useReducer((n) => n + 1, 0);
  // Re-render once on mount so target lookups have a layout to read from
  React.useEffect(() => { force(); }, []);
  if (!visible || !path || path.length === 0) return null;

  const resolveWp = (wp) => {
    if (wp.target) {
      const p = resolveTarget(wp.target);
      if (p) return { t: wp.t, x: p.x + (wp.dx || 0), y: p.y + (wp.dy || 0) };
      return { t: wp.t, x: wp.fallbackX || 1880, y: wp.fallbackY || 600 };
    }
    return wp;
  };
  const resolved = path.map(resolveWp);
  const resolvedClicks = clicks.map((c) => {
    if (c.target) {
      const p = resolveTarget(c.target);
      if (p) return { ...c, x: p.x + (c.dx || 0), y: p.y + (c.dy || 0) };
      return { ...c, x: c.fallbackX || 0, y: c.fallbackY || 0 };
    }
    return c;
  });
  clicks = resolvedClicks;

  const ts = resolved.map((p) => p.t);
  const xs = resolved.map((p) => p.x);
  const ys = resolved.map((p) => p.y);
  const x = interpolate(ts, xs, Easing.easeInOutCubic)(time);
  const y = interpolate(ts, ys, Easing.easeInOutCubic)(time);

  // Click "press" effect: cursor shrinks slightly at click moment
  let pressScale = 1;
  for (const c of clicks) {
    const dt = time - c.t;
    if (dt >= -0.05 && dt < 0.18) {
      const k = clamp((dt + 0.05) / 0.23, 0, 1);
      // ease in-out small bump
      pressScale = 1 - 0.18 * Math.sin(Math.PI * k);
    }
  }

  return (
    <React.Fragment>
      {/* Click ripples */}
      {clicks.map((c, i) => {
        const dt = time - c.t;
        if (dt < 0 || dt > 0.6) return null;
        const p = clamp(dt / 0.6, 0, 1);
        const eased = Easing.easeOutCubic(p);
        const r = 10 + eased * 36;
        const op = (1 - p) * 0.85;
        return (
          <div
            key={i}
            style={{
              position: 'absolute',
              left: c.x - r,
              top: c.y - r,
              width: r * 2,
              height: r * 2,
              borderRadius: 999,
              border: `2.5px solid ${c.color || '#3b82f6'}`,
              opacity: op,
              pointerEvents: 'none',
              zIndex: 9999,
            }}
          />
        );
      })}
      <div
        style={{
          position: 'absolute',
          left: x,
          top: y,
          pointerEvents: 'none',
          zIndex: 10000,
          filter: 'drop-shadow(0 3px 8px rgba(0,0,0,0.45))',
          transform: `translate(-2px, -2px) scale(${pressScale})`,
          transformOrigin: 'top left',
          willChange: 'transform',
        }}
      >
        <svg width="32" height="32" viewBox="0 0 22 22" style={{ display: 'block' }}>
          <path
            d="M3 2 L3 17 L7 13.5 L9.7 19.4 L12 18.4 L9.3 12.5 L14 12.5 Z"
            fill={color}
            stroke="#0a0a0c"
            strokeWidth="1.4"
            strokeLinejoin="round"
            strokeLinecap="round"
          />
        </svg>
      </div>
    </React.Fragment>
  );
}

// ── Realistic Chrome window frame ──────────────────────────────────────────
function BrowserChrome({
  x = 80,
  y = 60,
  width = 1760,
  height = 960,
  url = 'app.acme.io/reports',
  title = 'Acme · Reports',
  children,
}) {
  return (
    <div
      style={{
        position: 'absolute',
        left: x,
        top: y,
        width,
        height,
        borderRadius: 14,
        background: '#1c1c1f',
        boxShadow:
          '0 30px 80px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.06)',
        overflow: 'hidden',
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      {/* Top bar */}
      <div
        style={{
          height: 44,
          flexShrink: 0,
          display: 'flex',
          alignItems: 'center',
          gap: 10,
          padding: '0 14px',
          background: '#1f1f22',
          borderBottom: '1px solid rgba(255,255,255,0.06)',
        }}
      >
        {/* Traffic lights */}
        <div style={{ display: 'flex', gap: 8 }}>
          <div style={{ width: 13, height: 13, borderRadius: 99, background: '#ff5f57', boxShadow: 'inset 0 0 0 0.5px rgba(0,0,0,0.15)' }} />
          <div style={{ width: 13, height: 13, borderRadius: 99, background: '#febc2e', boxShadow: 'inset 0 0 0 0.5px rgba(0,0,0,0.15)' }} />
          <div style={{ width: 13, height: 13, borderRadius: 99, background: '#28c840', boxShadow: 'inset 0 0 0 0.5px rgba(0,0,0,0.15)' }} />
        </div>

        {/* Tab */}
        <div
          style={{
            marginLeft: 14,
            padding: '6px 14px',
            background: '#2b2b2f',
            borderRadius: '8px 8px 0 0',
            color: '#e5e7eb',
            fontSize: 12,
            fontWeight: 500,
            display: 'flex',
            alignItems: 'center',
            gap: 8,
            position: 'relative',
            top: 8,
            maxWidth: 220,
            whiteSpace: 'nowrap',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
          }}
        >
          <div
            style={{
              width: 12,
              height: 12,
              background: '#3b82f6',
              borderRadius: 3,
              flex: 'none',
            }}
          />
          {title}
        </div>

        {/* URL bar */}
        <div
          style={{
            marginLeft: 12,
            flex: 1,
            maxWidth: 760,
            height: 28,
            background: '#2b2b2f',
            borderRadius: 999,
            display: 'flex',
            alignItems: 'center',
            padding: '0 14px',
            color: '#a1a1aa',
            fontSize: 12,
            fontFamily: 'JetBrains Mono, ui-monospace, monospace',
            gap: 8,
          }}
        >
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#71717a" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
            <rect x="3" y="11" width="18" height="11" rx="2" />
            <path d="M7 11V7a5 5 0 0 1 10 0v4" />
          </svg>
          {url}
        </div>

        <div style={{ flex: 1 }} />

        {/* Right icons */}
        <div style={{ display: 'flex', gap: 10, alignItems: 'center', color: '#71717a' }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18" /></svg>
          <div style={{ width: 22, height: 22, borderRadius: 99, background: '#3a3a3f' }} />
        </div>
      </div>

      {/* Page content */}
      <div style={{ flex: 1, position: 'relative', overflow: 'hidden', background: '#fafafa' }}>
        {children}
      </div>
    </div>
  );
}

// ── Bottom-of-frame scene caption (Scene N + title + sub-caption) ──────────
function SceneCaption({ scene, title, caption }) {
  return (
    <div
      style={{
        position: 'absolute',
        left: 80,
        bottom: 28,
        right: 80,
        zIndex: 200,
        display: 'flex',
        alignItems: 'center',
        gap: 18,
        color: '#f5f5f7',
        pointerEvents: 'none',
      }}
    >
      <div
        style={{
          padding: '6px 14px',
          borderRadius: 999,
          background: 'rgba(59,130,246,0.16)',
          border: '1px solid rgba(59,130,246,0.45)',
          color: '#93c5fd',
          fontSize: 12.5,
          fontWeight: 700,
          letterSpacing: '0.1em',
        }}
      >
        SCENE {scene}
      </div>
      <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.01em' }}>{title}</div>
      <div
        style={{
          width: 1,
          height: 22,
          background: 'rgba(255,255,255,0.18)',
        }}
      />
      <div style={{ fontSize: 16, color: '#a1a1aa', fontWeight: 500 }}>{caption}</div>
    </div>
  );
}

// ── Feedzap brand mark + wordmark (mirrors components/brand/logo.tsx) ──────
function FeedzapMark({ size = 24, color = '#0f172a', glyphColor = '#fff' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" fill="none" style={{ display: 'block' }}>
      <rect x="1" y="1" width="30" height="26" rx="7" fill={color} />
      <path d="M11 27 L8 31 L15 27 Z" fill={color} />
      <path
        d="M17.5 6 L9.5 17 H15 L13.5 24 L22.5 12 H17 L17.5 6 Z"
        fill={glyphColor}
      />
    </svg>
  );
}

function FeedzapWordmark({ size = 22, color = '#0f172a', glyphColor = '#fff' }) {
  return (
    <span
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        gap: 8,
        fontWeight: 700,
        letterSpacing: '-0.02em',
        color,
        fontSize: size * 0.86,
      }}
    >
      <FeedzapMark size={size} color={color} glyphColor={glyphColor} />
      <span>Feedzap</span>
    </span>
  );
}

// ── Wraps a scene with smooth entry + exit fades ───────────────────────────
function SceneFade({ entryDur = 0.45, exitDur = 0.45, children }) {
  const { localTime, duration } = useSprite();
  let opacity = 1;
  if (localTime < entryDur) {
    opacity = Easing.easeOutCubic(clamp(localTime / entryDur, 0, 1));
  } else if (localTime > duration - exitDur) {
    opacity = Easing.easeInCubic(
      clamp((duration - localTime) / exitDur, 0, 1),
    );
  }
  return (
    <div
      style={{
        position: 'absolute',
        inset: 0,
        opacity,
        willChange: 'opacity',
      }}
    >
      {children}
    </div>
  );
}

// ── Tiny icon set used across scenes ───────────────────────────────────────
const Icons = {
  inbox: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <polyline points="22 12 16 12 14 15 10 15 8 12 2 12" />
      <path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />
    </svg>
  ),
  chart: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <line x1="12" y1="20" x2="12" y2="10" /><line x1="18" y1="20" x2="18" y2="4" /><line x1="6" y1="20" x2="6" y2="16" />
    </svg>
  ),
  sparkles: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3z" />
      <path d="M5 3v4M19 17v4M3 5h4M17 19h4" />
    </svg>
  ),
  bolt: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={color} stroke="none">
      <path d="M13 2 L4.09 12.97A1 1 0 0 0 4.91 14.5H10l-1 7.5 9.91-10.97A1 1 0 0 0 18.09 9.5H14z" />
    </svg>
  ),
  users: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M22 21v-2a4 4 0 0 0-3-3.87" /><path d="M16 3.13a4 4 0 0 1 0 7.75" />
    </svg>
  ),
  gear: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
    </svg>
  ),
  card: (size = 16, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <rect x="2" y="5" width="20" height="14" rx="2" /><line x1="2" y1="10" x2="22" y2="10" />
    </svg>
  ),
  download: (size = 14, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><polyline points="7 10 12 15 17 10" /><line x1="12" y1="15" x2="12" y2="3" />
    </svg>
  ),
  check: (size = 16, color = 'currentColor', stroke = 2.4) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round">
      <path d="M20 6 9 17l-5-5" />
    </svg>
  ),
  close: (size = 14, color = 'currentColor') => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M18 6 6 18" /><path d="m6 6 12 12" />
    </svg>
  ),
};

// Hovering arrow between scene "stages" — drawn into the inter-scene black border
// (used as visual chrome on the deck overview, not in scenes themselves).

Object.assign(window, {
  Cursor,
  BrowserChrome,
  SceneCaption,
  FeedzapMark,
  FeedzapWordmark,
  SceneFade,
  Icons,
});
