// Scroll-stitched video framework + atmosphere layers.
// Renders a fixed full-viewport stack of video layers; opacities are driven by scroll progress.
// Also renders the vignette, scroll-tint, grain, and cursor-torch overlays.

const { useEffect, useRef, useState } = React;

// === SECTION CLIPS ===
// Each entry: { id, label, src, hint, depthRange:[0..1, 0..1] }
// depthRange is the scroll-progress window where this clip is visible.
// To swap in real footage later, just replace `src` with a video URL.
const CLIPS = [
  { id: 'surface',   label: 'Surface · city night',   src: '', range: [0.00, 0.18] },
  { id: 'threshold', label: 'Threshold · descending', src: '', range: [0.12, 0.32] },
  { id: 'tunnel',    label: 'Tunnel · forward drift', src: '', range: [0.26, 0.55] },
  { id: 'chamber',   label: 'Chamber · single lamp',  src: '', range: [0.50, 0.74] },
  { id: 'cove',      label: 'Cove · ember reflection',src: '', range: [0.70, 0.92] },
  { id: 'void',      label: 'Void · single light',    src: '', range: [0.88, 1.00] },
];

// Map scroll-progress t to opacity within a [start,end] window with soft crossfade
function rangeOpacity(t, [a, b]) {
  if (t <= a || t >= b) return 0;
  const span = b - a;
  const fadeIn = Math.min(0.35, span * 0.4);
  const fadeOut = Math.min(0.35, span * 0.4);
  if (t < a + fadeIn) return (t - a) / fadeIn;
  if (t > b - fadeOut) return (b - t) / fadeOut;
  return 1;
}

// Placeholder gradient backgrounds keyed by clip id — gives the descent feel
// even before real footage is plugged in.
const PLACEHOLDER_GRADS = {
  surface:   'radial-gradient(ellipse at 50% 30%, #1a1d22 0%, #0a0b0d 70%)',
  threshold: 'radial-gradient(ellipse at 50% 60%, #14110d 0%, #060503 80%)',
  tunnel:    'radial-gradient(ellipse at 50% 50%, #0e0a06 0%, #020100 90%)',
  chamber:   'radial-gradient(ellipse at 35% 65%, #1a0e04 0%, #050200 80%)',
  cove:      'radial-gradient(ellipse at 60% 70%, #2a160a 0%, #08030a 75%)',
  void:      'radial-gradient(circle at 50% 55%, #0d0907 0%, #000 100%)',
};

const TINT_HUES = {
  warm:    { r: 18, g: 8,  b: 4  },   // smoky brass
  blue:    { r: 6,  g: 12, b: 22 },   // cave blue
  oxblood: { r: 22, g: 6,  b: 10 },   // dried red
  black:   { r: 0,  g: 0,  b: 0  },
};

function ScrollAtmosphere({ tw }) {
  const [progress, setProgress] = useState(0);
  const [mouse, setMouse] = useState({ x: 0.5, y: 0.5 });
  const containerRef = useRef(null);

  // scroll progress 0..1 across full document
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        const max = document.documentElement.scrollHeight - window.innerHeight;
        const p = max > 0 ? Math.min(1, Math.max(0, window.scrollY / max)) : 0;
        setProgress(p);
      });
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      cancelAnimationFrame(raf);
    };
  }, []);

  // cursor torch tracking (only if enabled)
  useEffect(() => {
    if (!tw.torch) return;
    const onMove = (e) => {
      setMouse({ x: e.clientX / window.innerWidth, y: e.clientY / window.innerHeight });
    };
    window.addEventListener('mousemove', onMove);
    return () => window.removeEventListener('mousemove', onMove);
  }, [tw.torch]);

  // tint color based on hue + scroll depth
  const hue = TINT_HUES[tw.tintHue] || TINT_HUES.warm;
  const tintAlpha = tw.scrollTint ? Math.min(0.55, progress * 0.7) : 0;
  const tintColor = `rgba(${hue.r}, ${hue.g}, ${hue.b}, ${tintAlpha})`;

  const vignette = (tw.vignette ?? 65) / 100;
  const grainOpacity = (tw.grain ?? 35) / 100 * 0.18;
  const parallaxAmp = (tw.parallax ?? 25) / 100;

  return (
    <div className="atmosphere" ref={containerRef} aria-hidden="true">
      {/* Layered video clips (or placeholder gradients) */}
      {CLIPS.map((clip) => {
        const opacity = rangeOpacity(progress, clip.range);
        if (opacity <= 0.001) return null;
        // Per-clip parallax: drift slightly upward as we approach end of range
        const localT = (progress - clip.range[0]) / (clip.range[1] - clip.range[0]);
        const drift = (localT - 0.5) * parallaxAmp * 80; // px
        return (
          <div
            key={clip.id}
            className="atmo-clip"
            style={{
              opacity,
              transform: `translate3d(0, ${drift}px, 0) scale(${1 + parallaxAmp * 0.06})`,
              background: tw.videoMode === 'placeholder' || !clip.src ? PLACEHOLDER_GRADS[clip.id] : 'transparent',
            }}
          >
            {tw.videoMode === 'video' && clip.src ? (
              <video
                src={clip.src}
                autoPlay
                muted
                loop
                playsInline
                preload="auto"
                style={{ width: '100%', height: '100%', objectFit: 'cover' }}
              />
            ) : null}
          </div>
        );
      })}

      {/* Scroll tint pass */}
      <div
        className="atmo-tint"
        style={{
          background: tintColor,
          mixBlendMode: tw.scrollTint ? 'multiply' : 'normal',
        }}
      />

      {/* Vignette */}
      <div
        className="atmo-vignette"
        style={{
          background: `radial-gradient(ellipse at 50% 50%,
            transparent 0%,
            transparent ${30 + (1 - vignette) * 40}%,
            rgba(0,0,0,${vignette * 0.55}) 70%,
            rgba(0,0,0,${vignette * 0.92}) 100%)`,
        }}
      />

      {/* Cursor torch */}
      {tw.torch ? (
        <div
          className="atmo-torch"
          style={{
            background: `radial-gradient(circle at ${mouse.x * 100}% ${mouse.y * 100}%,
              rgba(220, 175, 105, 0.18) 0%,
              rgba(220, 175, 105, 0.08) 12%,
              transparent 28%)`,
          }}
        />
      ) : null}

      {/* Grain */}
      <div
        className="atmo-grain"
        style={{ opacity: grainOpacity }}
      />
    </div>
  );
}

window.ScrollAtmosphere = ScrollAtmosphere;
window.SNARE_CLIPS = CLIPS;
