// title-card.jsx — Title cards illuminated: aurora + sparkles + shimmer
// 2s duration per card, each acto uses its own module color for the halo.
//
// Visual breakdown:
//   • Aurora halo behind title using module color (radial gradient + blur)
//   • Secondary radial glow that breathes slowly
//   • 16 deterministic sparkles (white / violet / blue / accent / gold)
//     positioned in a donut around the title, floating upward as they twinkle
//   • Title with subtle drop-shadow glow + shimmer wave that sweeps left→right
//   • Subtitle fades in after title
//
// Exports on window: TitleCard

function TitleCard({ actNum, name, sub, color = '#007AFF' }) {
  const { localTime, duration } = useSprite();

  // Master enter/exit fade
  const fadeIn = 0.35;
  const fadeOut = 0.35;
  let mainOpacity = 1;
  if (localTime < fadeIn) mainOpacity = localTime / fadeIn;
  else if (localTime > duration - fadeOut) {
    mainOpacity = Math.max(0, 1 - (localTime - (duration - fadeOut)) / fadeOut);
  }

  // Title slide-in: 0.15-0.6
  const titleP = clamp((localTime - 0.15) / 0.45, 0, 1);
  const titleE = Easing.easeOutCubic(titleP);
  // Title gentle breathing pulse (after entrance)
  const titlePulse = titleP >= 1 ? 1 + 0.012 * Math.sin((localTime - 0.6) * Math.PI * 1.3) : 1;

  // Subtitle: 0.7-1.15
  const subP = clamp((localTime - 0.7) / 0.45, 0, 1);
  const subE = Easing.easeOutCubic(subP);

  // Shimmer position: sweeps from -10% to 110% over 0.4-1.2s
  const shimmerP = clamp((localTime - 0.4) / 0.8, 0, 1);
  const shimmerX = -10 + shimmerP * 120;

  // Second shimmer pass later in the card (1.8-2.6s)
  const shimmer2P = clamp((localTime - 1.8) / 0.8, 0, 1);
  const shimmer2X = -10 + shimmer2P * 120;
  const useShimmer2 = shimmer2P > 0 && shimmer2P < 1;
  const effectiveShimmerX = useShimmer2 ? shimmer2X : shimmerX;

  // Underline draw: 0.5-1.1
  const underlineP = clamp((localTime - 0.5) / 0.6, 0, 1);
  const underlineE = Easing.easeOutCubic(underlineP);

  // Scan line — diagonal sweep across screen 0.3-1.0
  const scanP = clamp((localTime - 0.25) / 0.75, 0, 1);

  // Aurora breathe — slow pulse
  const breathe = 0.85 + 0.15 * Math.sin(localTime * Math.PI * 0.9);

  // Light rays rotation
  const rayRotation = localTime * 18;

  // Initial burst at 0.25-0.75
  const burstP = clamp((localTime - 0.25) / 0.5, 0, 1);

  // Subtitle burst (smaller, when subtitle appears) 0.7-1.2
  const subBurstP = clamp((localTime - 0.7) / 0.5, 0, 1);

  // Sparkles
  const sparkles = makeSparkles(actNum, color);
  const burstParticles = makeBurstParticles(actNum, color);
  const bokehBlobs = makeBokehBlobs(actNum, color);

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: '#06070a',
      zIndex: 40,
      opacity: mainOpacity,
      overflow: 'hidden',
    }}>
      {/* Bokeh background blobs — slow floating soft circles */}
      {bokehBlobs.map((b, i) => (
        <BokehBlob key={i} {...b} localTime={localTime} duration={duration} />
      ))}

      {/* Aurora halo — module color radial gradient */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(ellipse 65% 50% at 50% 50%, ${hexToRgba(color, 0.22)} 0%, ${hexToRgba(color, 0.08)} 35%, transparent 70%)`,
        opacity: titleP * breathe,
        willChange: 'opacity',
      }} />

      {/* Light rays — 8 thin radiating rays, rotating */}
      <div style={{
        position: 'absolute',
        top: '50%', left: '50%',
        width: 1, height: 1,
        transform: `translate(-50%, -50%) rotate(${rayRotation}deg)`,
        opacity: titleP * 0.55,
        willChange: 'transform',
      }}>
        {Array.from({ length: 12 }, (_, i) => (
          <div key={i} style={{
            position: 'absolute',
            top: 0, left: 0,
            width: 2,
            height: 700,
            background: `linear-gradient(to bottom, transparent 0%, ${hexToRgba(color, 0.35)} 40%, ${hexToRgba(color, 0.18)} 70%, transparent 100%)`,
            transform: `translate(-50%, -50%) rotate(${i * 30}deg) translateY(-50%)`,
            transformOrigin: 'top center',
            filter: 'blur(2px)',
          }} />
        ))}
      </div>

      {/* Secondary diffuse glow — adds depth */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `radial-gradient(circle at 50% 50%, ${hexToRgba(color, 0.14)} 0%, transparent 55%)`,
        opacity: titleP * 0.9,
        filter: 'blur(60px)',
      }} />

      {/* Cool ambient color at edges (deep violet/blue) */}
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(ellipse 100% 60% at 20% 100%, rgba(123, 70, 220, 0.10) 0%, transparent 60%), radial-gradient(ellipse 100% 60% at 80% 0%, rgba(60, 110, 220, 0.10) 0%, transparent 60%)',
        opacity: titleP,
      }} />

      {/* Initial burst particles — explode outward from center at title-in */}
      {burstParticles.map((p, i) => (
        <BurstParticle key={i} {...p} burstP={burstP} />
      ))}

      {/* Subtitle burst — smaller, second wave when subtitle appears */}
      {burstParticles.slice(0, 12).map((p, i) => (
        <BurstParticle key={'sub' + i} {...p} distance={p.distance * 0.55} size={p.size * 0.7} burstP={subBurstP} />
      ))}

      {/* Diagonal scan line — thin white streak crosses screen once */}
      {scanP > 0 && scanP < 1 && (
        <div style={{
          position: 'absolute',
          top: 0, left: `${-30 + scanP * 160}%`,
          width: 280,
          height: '120%',
          background: 'linear-gradient(105deg, transparent 0%, rgba(255,255,255,0.05) 35%, rgba(255,255,255,0.18) 50%, rgba(255,255,255,0.05) 65%, transparent 100%)',
          transform: 'rotate(15deg)',
          filter: 'blur(1px)',
          pointerEvents: 'none',
          mixBlendMode: 'screen',
        }} />
      )}

      {/* Sparkles */}
      {sparkles.map((sp, i) => (
        <SparkleParticle key={i} {...sp} localTime={localTime} />
      ))}

      {/* Content (title + subtitle) */}
      <div style={{
        position: 'absolute',
        top: '50%', left: '50%',
        transform: 'translate(-50%, -50%)',
        textAlign: 'center',
        width: '100%',
        zIndex: 2,
      }}>
        {/* Title with shimmer wave */}
        <h1 style={{
          fontSize: 88,
          fontWeight: 700,
          letterSpacing: '-0.04em',
          margin: 0,
          marginBottom: 22,
          lineHeight: 1.0,
          opacity: titleE,
          transform: `translateY(${(1 - titleE) * 14}px) scale(${titlePulse})`,
          // Layered text shadows for glow effect using module color
          filter: `drop-shadow(0 0 24px ${hexToRgba(color, 0.55)}) drop-shadow(0 0 56px ${hexToRgba(color, 0.30)})`,
          // Shimmer: subtle brightness wave (base 0.92, peak 1.0) — text stays readable always
          backgroundImage: `linear-gradient(105deg,
            rgba(255,255,255,0.92) 0%,
            rgba(255,255,255,0.92) ${Math.max(0, effectiveShimmerX - 12)}%,
            rgba(255,255,255,1.00) ${effectiveShimmerX}%,
            rgba(255,255,255,0.92) ${Math.min(100, effectiveShimmerX + 14)}%,
            rgba(255,255,255,0.92) 100%)`,
          WebkitBackgroundClip: 'text',
          backgroundClip: 'text',
          WebkitTextFillColor: 'transparent',
          willChange: 'transform, opacity, background-image',
        }}>
          {name}
        </h1>

        {/* Animated underline accent — draws under the title */}
        <div style={{
          margin: '0 auto 18px',
          width: `${underlineE * 180}px`,
          height: 2.5,
          background: `linear-gradient(90deg, transparent, ${color}, ${hexToRgba(color, 0.8)}, transparent)`,
          borderRadius: 2,
          opacity: underlineE,
          boxShadow: `0 0 14px ${hexToRgba(color, 0.7)}, 0 0 28px ${hexToRgba(color, 0.4)}`,
          transition: 'width 200ms',
        }} />

        {sub && (
          <p style={{
            fontSize: 19,
            fontWeight: 400,
            color: 'rgba(255,255,255,0.62)',
            letterSpacing: '0.005em',
            margin: 0,
            opacity: subE,
            transform: `translateY(${(1 - subE) * 10}px)`,
            willChange: 'transform, opacity',
          }}>
            {sub}
          </p>
        )}
      </div>
    </div>
  );
}

// ── Sparkle particle (4-pointed star with glow) ─────────────────────
function SparkleParticle({ x, y, size, color, delay, life, drift, localTime }) {
  const t = localTime - delay;
  if (t < 0 || t > life) return null;

  const p = t / life;
  // Scale curve: small → big → small (sine)
  const scale = Math.sin(p * Math.PI);
  const opacity = scale * 0.95;
  // Upward drift
  const yOffset = -drift * p;
  // Slow rotation
  const rotation = p * 90;

  return (
    <div style={{
      position: 'absolute',
      left: `${x}%`,
      top: `calc(${y}% + ${yOffset}px)`,
      transform: `translate(-50%, -50%) scale(${scale}) rotate(${rotation}deg)`,
      opacity,
      pointerEvents: 'none',
      filter: `drop-shadow(0 0 ${size * 0.7}px ${color}) drop-shadow(0 0 ${size * 1.5}px ${hexToRgba(color, 0.6)})`,
      willChange: 'transform, opacity',
    }}>
      <svg viewBox="0 0 24 24" width={size} height={size} style={{ display: 'block' }}>
        <path d="M12 0 L13.8 10.2 L24 12 L13.8 13.8 L12 24 L10.2 13.8 L0 12 L10.2 10.2 Z" fill={color} />
      </svg>
    </div>
  );
}

// ── Generate deterministic sparkle layout per actNum ────────────────
function makeSparkles(seed, accentColor) {
  const colors = ['#ffffff', '#a78bfa', '#60a5fa', accentColor, '#fde68a', '#fbcfe8'];
  const sparkles = [];

  const rand = (i, salt) => {
    const v = Math.sin((seed + 0.7) * 1000 + i * 137 + salt * 41) * 10000;
    return v - Math.floor(v);
  };

  const COUNT = 18;
  for (let i = 0; i < COUNT; i++) {
    // Place sparkles in a donut around center (avoids text)
    const angle = rand(i, 1) * Math.PI * 2;
    const r = 0.22 + rand(i, 2) * 0.34; // 22-56% normalized distance
    let x = 50 + Math.cos(angle) * r * 80;
    let y = 50 + Math.sin(angle) * r * 55;
    x = Math.max(4, Math.min(96, x));
    y = Math.max(8, Math.min(92, y));

    sparkles.push({
      x,
      y,
      size: 5 + rand(i, 3) * 8,
      color: colors[Math.floor(rand(i, 4) * colors.length)],
      delay: 0.15 + (i / COUNT) * 1.55, // staggered across the 2s
      life: 0.65 + rand(i, 6) * 0.45,
      drift: 10 + rand(i, 7) * 18,
    });
  }
  return sparkles;
}

function hexToRgba(hex, alpha) {
  const h = hex.replace('#', '');
  const r = parseInt(h.slice(0, 2), 16);
  const g = parseInt(h.slice(2, 4), 16);
  const b = parseInt(h.slice(4, 6), 16);
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

// ── Burst particle: explodes outward from center during initial title-in ──
function BurstParticle({ angle, distance, size, color, burstP }) {
  if (burstP <= 0 || burstP >= 1) return null;
  const e = Easing.easeOutCubic(burstP);
  const r = distance * e;
  const x = Math.cos(angle) * r;
  const y = Math.sin(angle) * r;
  // Fade out toward the end of burst
  const opacity = burstP < 0.6 ? 1 : (1 - (burstP - 0.6) / 0.4);
  const scale = 0.4 + 0.6 * Math.sin(burstP * Math.PI);
  return (
    <div style={{
      position: 'absolute',
      top: '50%', left: '50%',
      width: size, height: size,
      borderRadius: '50%',
      background: color,
      transform: `translate(${x}px, ${y}px) translate(-50%, -50%) scale(${scale})`,
      opacity,
      pointerEvents: 'none',
      filter: `drop-shadow(0 0 ${size * 1.2}px ${color}) drop-shadow(0 0 ${size * 2.5}px ${hexToRgba(color, 0.6)})`,
      willChange: 'transform, opacity',
    }} />
  );
}

function makeBurstParticles(seed, accentColor) {
  const colors = ['#ffffff', accentColor, '#a78bfa', '#60a5fa', '#fde68a'];
  const N = 20;
  const rand = (i, salt) => {
    const v = Math.sin((seed + 1.3) * 1000 + i * 91 + salt * 53) * 10000;
    return v - Math.floor(v);
  };
  const particles = [];
  for (let i = 0; i < N; i++) {
    const angle = (i / N) * Math.PI * 2 + rand(i, 1) * 0.4; // mostly uniform with jitter
    particles.push({
      angle,
      distance: 90 + rand(i, 2) * 180, // 90-270px outward
      size: 3 + rand(i, 3) * 5,
      color: colors[Math.floor(rand(i, 4) * colors.length)],
    });
  }
  return particles;
}

// ── Bokeh blob: large soft floating background circle ──
function BokehBlob({ x0, y0, x1, y1, size, color, alpha, localTime, duration }) {
  const p = clamp(localTime / duration, 0, 1);
  const x = x0 + (x1 - x0) * p;
  const y = y0 + (y1 - y0) * p;
  // Subtle opacity envelope: fade in 0-0.4, hold, fade out 0.7-1
  let envOpacity = 1;
  if (p < 0.25) envOpacity = p / 0.25;
  else if (p > 0.75) envOpacity = (1 - p) / 0.25;
  return (
    <div style={{
      position: 'absolute',
      left: `${x}%`, top: `${y}%`,
      width: size, height: size,
      borderRadius: '50%',
      background: `radial-gradient(circle, ${hexToRgba(color, alpha)} 0%, ${hexToRgba(color, alpha * 0.4)} 40%, transparent 70%)`,
      transform: 'translate(-50%, -50%)',
      filter: 'blur(32px)',
      opacity: envOpacity * 0.85,
      pointerEvents: 'none',
      willChange: 'opacity',
    }} />
  );
}

function makeBokehBlobs(seed, accentColor) {
  const palette = [accentColor, '#a78bfa', '#60a5fa', '#ec4899', '#fbbf24'];
  const N = 5;
  const rand = (i, salt) => {
    const v = Math.sin((seed + 2.7) * 1000 + i * 173 + salt * 67) * 10000;
    return v - Math.floor(v);
  };
  const blobs = [];
  for (let i = 0; i < N; i++) {
    blobs.push({
      x0: 5 + rand(i, 1) * 90,
      y0: 5 + rand(i, 2) * 90,
      x1: 5 + rand(i, 3) * 90,
      y1: 5 + rand(i, 4) * 90,
      size: 180 + rand(i, 5) * 220, // 180-400px
      color: palette[Math.floor(rand(i, 6) * palette.length)],
      alpha: 0.18 + rand(i, 7) * 0.10,
    });
  }
  return blobs;
}

Object.assign(window, { TitleCard });
