// Wasabil — Scroll-Driven Video Intro (Mercury style)
//
// 4 fases con el scroll:
//   0   → 0.45  Scrub frame-by-frame del video.
//   0.45 → 0.58 Paneles laterales entran desde los lados y cubren la pantalla.
//   0.58 → 0.88 Texto "Bienvenido" aparece y se mantiene en el centro.
//   0.88 → 1.0  Texto desaparece, paneles se abren y revelan el Hero React.

function ScrollVideoIntro({
  frameCount = 120,
  framePath = "/assets/hero-frames/frame-",
  scrollLength = 2.6,
  containerStyle,
}) {
  if (window.innerWidth < 768) return null;

  const canvasRef = React.useRef(null);
  const wrapperRef = React.useRef(null);
  const cardRef = React.useRef(null);
  const stickyRef = React.useRef(null);
  const leftPanelRef = React.useRef(null);
  const rightPanelRef = React.useRef(null);
  const welcomeRef = React.useRef(null);
  const heroCoverRef = React.useRef(null);
  const currentFrame = React.useRef(-1);
  const rafRef = React.useRef(null);
  const [done, setDone] = React.useState(false);

  React.useEffect(() => {
    if ("scrollRestoration" in window.history) window.history.scrollRestoration = "manual";
    window.scrollTo(0, 0);

    // Solapar el Hero con la última pantalla del wrapper para que ya esté
    // posicionado en su sitio cuando los paneles se abren — no que "suba".
    const nextSibling = wrapperRef.current?.nextElementSibling;
    let prevHeroMargin = "";
    if (nextSibling) {
      prevHeroMargin = nextSibling.style.marginTop;
      nextSibling.style.marginTop = "-100vh";
    }

    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    let mounted = true;
    const pad = (n) => String(n).padStart(3, "0");
    const imgs = [];
    let firstReady = false;

    const renderFrame = (idx) => {
      const img = imgs[idx];
      if (!img || !img.complete || !img.naturalWidth) return;
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      const cw = canvas.clientWidth, ch = canvas.clientHeight;
      if (canvas.width !== cw * dpr || canvas.height !== ch * dpr) {
        canvas.width = cw * dpr;
        canvas.height = ch * dpr;
      }
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      const iw = img.naturalWidth, ih = img.naturalHeight;
      const scale = Math.max(cw / iw, ch / ih);
      const dw = iw * scale, dh = ih * scale;
      ctx.clearRect(0, 0, cw, ch);
      ctx.drawImage(img, (cw - dw) / 2, (ch - dh) / 2, dw, dh);
      currentFrame.current = idx;
    };

    for (let i = 0; i < frameCount; i++) {
      const im = new Image();
      im.src = `${framePath}${pad(i + 1)}.jpg`;
      if (i === 0) im.onload = () => { if (mounted) { firstReady = true; renderFrame(0); } };
      imgs[i] = im;
    }

    const lerp = (a, b, t) => a + (b - a) * t;
    const clamp01 = (v) => Math.max(0, Math.min(1, v));

    const onScroll = () => {
      if (rafRef.current) return;
      rafRef.current = requestAnimationFrame(() => {
        rafRef.current = null;
        const wrap = wrapperRef.current;
        const card = cardRef.current;
        const leftPanel = leftPanelRef.current;
        const rightPanel = rightPanelRef.current;
        const welcome = welcomeRef.current;
        const heroCover = heroCoverRef.current;
        if (!wrap || !card) return;

        const rect = wrap.getBoundingClientRect();
        const total = wrap.offsetHeight - window.innerHeight;
        const progress = total > 0 ? clamp01(-rect.top / total) : 0;

        // Fase 1: scrub frames (0 → 0.45)
        const scrubProgress = clamp01(progress / 0.45);
        const idx = Math.min(frameCount - 1, Math.floor(scrubProgress * (frameCount - 1)));
        if (idx !== currentFrame.current) renderFrame(idx);

        // Paneles: posición según fase
        // Fase 2 (0.45 → 0.58): cierre
        // Fase 3 (0.58 → 0.88): mantenidos
        // Fase 4 (0.88 → 1.00): apertura
        let leftX, rightX;
        if (progress < 0.45) {
          leftX = -100; rightX = 100;
        } else if (progress < 0.58) {
          const t = (progress - 0.45) / 0.13;
          const e = 1 - Math.pow(1 - t, 2.5);
          leftX  = lerp(-100, 0, e);
          rightX = lerp( 100, 0, e);
        } else if (progress < 0.88) {
          leftX = 0; rightX = 0;
        } else {
          const t = (progress - 0.88) / 0.12;
          const e = 1 - Math.pow(1 - t, 2.5);
          leftX  = lerp(0, -100, e);
          rightX = lerp(0,  100, e);
        }
        if (leftPanel)  leftPanel.style.transform  = `translateX(${leftX.toFixed(2)}%)`;
        if (rightPanel) rightPanel.style.transform = `translateX(${rightX.toFixed(2)}%)`;

        // "Bienvenido": fade-in 0.56→0.66, mantenido hasta 0.88, fade-out 0.88→0.96
        let welcomeOpacity = 0;
        let welcomeAppear = 0;
        if (progress >= 0.56 && progress < 0.96) {
          if (progress < 0.66) {
            welcomeAppear = clamp01((progress - 0.56) / 0.10);
            welcomeAppear = 1 - Math.pow(1 - welcomeAppear, 2);
            welcomeOpacity = welcomeAppear;
          } else if (progress < 0.88) {
            welcomeAppear = 1;
            welcomeOpacity = 1;
          } else {
            welcomeAppear = 1;
            const fadeT = (progress - 0.88) / 0.08;
            welcomeOpacity = 1 - clamp01(fadeT);
          }
        }
        if (welcome) {
          welcome.style.opacity = welcomeOpacity.toFixed(3);
          const lift = lerp(16, 0, welcomeAppear);
          const scale = lerp(0.95, 1, welcomeAppear);
          welcome.style.transform = `translate(-50%, calc(-50% + ${lift.toFixed(1)}px)) scale(${scale.toFixed(3)})`;
        }

        // heroCover: oculta el Hero React durante fases 1–3.
        // En fase 4 (0.88 → 1.0) hace fade-out para revelar el Hero limpio.
        if (heroCover) {
          let coverOpacity = 1;
          if (progress >= 0.88) {
            const t = (progress - 0.88) / 0.12;
            coverOpacity = 1 - clamp01(t);
          }
          heroCover.style.opacity = coverOpacity.toFixed(3);
          heroCover.style.pointerEvents = coverOpacity < 0.05 ? "none" : "auto";
        }

        // Cuando completamos toda la animación, marcamos done para desmontar
        // el wrapper. A partir de ahí el sitio queda con el Hero como tope
        // absoluto: scrollear arriba no vuelve a mostrar la intro.
        if (progress >= 0.999) {
          setDone(true);
          return;
        }

        // El card del video se apaga gradualmente entre 0.50–0.58 mientras los
        // paneles aún están cerrando. A partir de 0.58 ya está cubierto.
        if (card) {
          let cardOpacity = 1;
          if (progress >= 0.58) {
            cardOpacity = 0;
          } else if (progress >= 0.50) {
            cardOpacity = 1 - clamp01((progress - 0.50) / 0.08);
          }
          card.style.opacity = cardOpacity.toFixed(3);
        }

        // En la fase 4 (0.85 → 1.0), cuando los paneles se abren, lo que aparece
        // detrás debe ser el Hero React (no el video). El cover ya hace fade-out
        // en esa fase, pero los paneles dejan ver lo que hay detrás del sticky.
        // Como el sticky solo contiene el card (ya invisible), los paneles
        // (con su propio fondo sólido) y el welcome — al abrirse los paneles,
        // se ve el cover apagándose, debajo está el Hero. Perfecto.
      });
    };
    const onResize = () => { if (currentFrame.current >= 0) renderFrame(currentFrame.current); };

    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onResize);
    onScroll();

    return () => {
      mounted = false;
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onResize);
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      if (nextSibling) nextSibling.style.marginTop = prevHeroMargin;
    };
  }, [frameCount, framePath]);

  // Cuando se completa la animación, restaurar margin del Hero a 0
  // (no -100vh) y scroll al inicio.
  React.useEffect(() => {
    if (!done) return;
    const nextSibling = wrapperRef.current?.nextElementSibling
      || document.querySelector(".hero-section");
    if (nextSibling) nextSibling.style.marginTop = "";
    window.scrollTo(0, 0);
  }, [done]);

  if (done) return null;

  const baseStyle = containerStyle ?? {
    width: "min(70vw, 117vh)",
    aspectRatio: "16 / 9",
    borderRadius: 24,
    overflow: "hidden",
    background: "#000",
    boxShadow: "0 30px 80px -20px rgba(0,0,0,0.45)",
  };

  const panelBase = {
    position: "absolute",
    top: 0,
    bottom: 0,
    width: "52%",
    background: "var(--bg, #121219)",
    willChange: "transform",
    zIndex: 6,
  };

  return (
    <>
      {/* Cover sólido sobre el Hero — lo oculta hasta que la transición termine.
          Está en posición fixed pero solo es visible cuando el sticky está activo
          (durante el wrapper). Al terminar el wrapper, su opacidad ya llegó a 0. */}
      <div
        ref={heroCoverRef}
        style={{
          position: "fixed",
          inset: 0,
          background: "var(--bg, #121219)",
          opacity: 1,
          zIndex: 4,
          pointerEvents: "none",
          willChange: "opacity",
        }}
        aria-hidden="true"
      />

      <div
        ref={wrapperRef}
        style={{
          position: "relative",
          height: `${scrollLength * 100}vh`,
          background: "var(--bg, #121219)",
        }}
      >
        <div
          ref={stickyRef}
          style={{
            position: "sticky",
            top: 0,
            height: "100vh",
            width: "100%",
            display: "grid",
            placeItems: "center",
            overflow: "hidden",
            pointerEvents: "none",
            zIndex: 5,
          }}
        >
          <div ref={cardRef} style={baseStyle}>
            <canvas ref={canvasRef} style={{ display: "block", width: "100%", height: "100%" }}/>
          </div>

          {/* Paneles laterales */}
          <div
            ref={leftPanelRef}
            style={{
              ...panelBase,
              left: 0,
              transform: "translateX(-100%)",
              boxShadow: "inset -1px 0 0 rgba(180, 220, 90, 0.10)",
            }}
          />
          <div
            ref={rightPanelRef}
            style={{
              ...panelBase,
              right: 0,
              transform: "translateX(100%)",
              boxShadow: "inset 1px 0 0 rgba(180, 220, 90, 0.10)",
            }}
          />

          {/* Texto "Bienvenido" en el medio */}
          <div
            ref={welcomeRef}
            style={{
              position: "absolute",
              top: "50%",
              left: "50%",
              transform: "translate(-50%, calc(-50% + 16px)) scale(0.95)",
              opacity: 0,
              zIndex: 7,
              color: "var(--ink, #f3efe7)",
              fontFamily: "var(--serif, 'Instrument Serif', serif)",
              fontSize: "clamp(36px, 6vw, 96px)",
              lineHeight: 1.1,
              letterSpacing: "-0.025em",
              fontWeight: 400,
              whiteSpace: "normal",
              textAlign: "center",
              maxWidth: "72vw",
              willChange: "transform, opacity",
              pointerEvents: "none",
              textShadow: "0 8px 40px rgba(0,0,0,0.4)",
            }}
          >
            Bienvenido al futuro de las finanzas
            <em style={{
              fontStyle: "italic",
              color: "var(--accent, oklch(0.78 0.18 130))",
              marginLeft: "0.05em",
            }}>.</em>
          </div>
        </div>
      </div>
    </>
  );
}

Object.assign(window, { ScrollVideoIntro });
