// Background composition: 3 chrome image layers + bloom + haze + grid + cursor light.
// Animations: idle sinusoidal drift, scroll parallax (smoothed), click pulse decay.

const { useEffect, useRef, useState } = React;

function LiquidBackground() {
  const layer1Ref = useRef(null);
  const layer2Ref = useRef(null);
  const layer3Ref = useRef(null);
  const bloomRef = useRef(null);
  const gridRef = useRef(null);
  const lightRef = useRef(null);
  const state = useRef({
    px: 0, py: 0,             // raw mouse position
    mx: 0, my: 0,             // smoothed mouse
    lx: -9999, ly: -9999,     // smoothed light position
    scrollY: 0,               // raw scroll
    scrollSmooth: 0,          // lerped scroll position
    scrollVel: 0,             // |delta scroll| smoothed (for reactive flutter)
    lastScrollY: 0,
    pulse: 0,                 // click pulse, decays each frame
  });

  // Wave-like motion: all layers drift in the SAME direction but with phase
  // offsets, so the whole surface looks like a slow sea, not three things
  // pulling apart.
  const baseLayer = [
    { scale: 1.15, rot: 0,    driftAmpX: 70,  driftAmpY: 110, driftSpeed: 0.045, driftPhase: 0,   parallax: 0.06, mouseAmp: 14 },
    { scale: 1.30, rot: 1.5,  driftAmpX: 95,  driftAmpY: 130, driftSpeed: 0.038, driftPhase: 1.6, parallax: 0.10, mouseAmp: 20 },
    { scale: 1.40, rot: -1.5, driftAmpX: 80,  driftAmpY: 120, driftSpeed: 0.032, driftPhase: 3.4, parallax: 0.08, mouseAmp: 17 },
  ];

  useEffect(() => {
    const onMove = (e) => {
      const w = window.innerWidth, h = window.innerHeight;
      state.current.px = e.clientX;
      state.current.py = e.clientY;
      state.current.mx = (e.clientX / w - 0.5) * 2;
      state.current.my = (e.clientY / h - 0.5) * 2;
      if (lightRef.current) lightRef.current.classList.add("on");
    };
    const onLeave = () => {
      if (lightRef.current) lightRef.current.classList.remove("on");
    };
    const onClick = () => {
      state.current.pulse = Math.min(state.current.pulse + 0.6, 1);
    };
    const onScroll = () => {
      state.current.scrollY = window.scrollY;
    };

    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseleave", onLeave);
    window.addEventListener("blur", onLeave);
    window.addEventListener("click", onClick);
    window.addEventListener("scroll", onScroll, { passive: true });

    let raf;
    const startTime = performance.now();

    const tick = () => {
      const now = performance.now();
      const t = (now - startTime) / 1000;
      const s = state.current;

      // Smooth scroll position
      s.scrollSmooth += (s.scrollY - s.scrollSmooth) * 0.08;
      // Scroll velocity (absolute, smoothed)
      const rawVel = Math.abs(s.scrollY - s.lastScrollY);
      s.scrollVel += (rawVel - s.scrollVel) * 0.10;
      s.lastScrollY = s.scrollY;
      // Pulse decay
      s.pulse *= 0.92;

      const refs = [layer1Ref.current, layer2Ref.current, layer3Ref.current];

      refs.forEach((el, i) => {
        if (!el) return;
        const b = baseLayer[i];
        // Sinusoidal idle drift — slow ocean swell
        const dx = Math.sin(t * b.driftSpeed + b.driftPhase) * b.driftAmpX;
        const dy = Math.cos(t * b.driftSpeed * 0.82 + b.driftPhase) * b.driftAmpY;
        const dr = Math.sin(t * b.driftSpeed * 0.5 + b.driftPhase) * 0.4; // very subtle rotation drift

        // Scroll parallax (smoothed): each layer moves at slightly different speed
        const sy = -s.scrollSmooth * b.parallax;
        // Scroll velocity adds a tiny "flutter" — stretches scale & rotation
        const velFactor = Math.min(s.scrollVel / 80, 1);
        const velScale = velFactor * 0.012 * (i + 1) * 0.5;
        const velRot   = velFactor * 0.25 * (i % 2 === 0 ? 1 : -1);

        // Mouse very subtle parallax
        const mx = s.mx * b.mouseAmp;
        const my = s.my * b.mouseAmp * 0.6;

        // Click pulse — small additive scale that decays
        const pulseScale = s.pulse * 0.015;

        const scale = b.scale + velScale + pulseScale;
        const rot   = b.rot + dr + velRot;

        el.style.transform =
          `translate3d(${dx + mx}px, ${dy + my + sy}px, 0) ` +
          `scale(${scale}) ` +
          `rotate(${rot}deg)`;
      });

      // Iridescent bloom — slow drift (already CSS-animated, add a touch of mouse)
      if (bloomRef.current) {
        const bx = s.mx * -10;
        const by = s.my * -10;
        bloomRef.current.style.transform = `translate3d(${bx}px, ${by}px, 0)`;
      }

      // Grid drift toward cursor
      if (gridRef.current) {
        const gx = s.mx * -8;
        const gy = s.my * -8;
        gridRef.current.style.transform = `translate3d(${gx}px, ${gy}px, 0)`;
      }

      // Cursor light
      if (lightRef.current) {
        s.lx += (s.px - s.lx) * 0.22;
        s.ly += (s.py - s.ly) * 0.22;
        lightRef.current.style.transform = `translate3d(${s.lx - 140}px, ${s.ly - 140}px, 0)`;
      }

      raf = requestAnimationFrame(tick);
    };
    tick();

    return () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseleave", onLeave);
      window.removeEventListener("blur", onLeave);
      window.removeEventListener("click", onClick);
      window.removeEventListener("scroll", onScroll);
      cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <div className="bg-stack" aria-hidden="true">
      <svg width="0" height="0" style={{ position: "absolute" }}>
        <defs>
          <filter id="liquid-glass" x="-10%" y="-10%" width="120%" height="120%">
            <feTurbulence type="fractalNoise" baseFrequency="0.012" numOctaves="2" seed="3" result="noise">
              <animate attributeName="baseFrequency" values="0.012;0.018;0.012" dur="14s" repeatCount="indefinite" />
            </feTurbulence>
            <feDisplacementMap in="SourceGraphic" in2="noise" scale="10" xChannelSelector="R" yChannelSelector="G" />
          </filter>
        </defs>
      </svg>

      <div className="bg-haze" />
      <div className="bg-grid" ref={gridRef} />
      <div className="cursor-light" ref={lightRef} />
    </div>
  );
}

function MagneticCursor() { return null; }

function useSmoothScroll() {
  useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    document.documentElement.style.scrollBehavior = "smooth";
    return () => { document.documentElement.style.scrollBehavior = ""; };
  }, []);
}

function useReveal() {
  useEffect(() => {
    const reveal = (el) => el.classList.add("in");
    const all = () => document.querySelectorAll(".reveal:not(.in)");

    const vh = window.innerHeight;
    let i = 0;
    all().forEach((el) => {
      const r = el.getBoundingClientRect();
      if (r.top < vh * 0.95) {
        setTimeout(() => reveal(el), Math.min(i * 40, 480));
        i++;
      }
    });

    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          reveal(e.target);
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0, rootMargin: "0px 0px -10% 0px" });
    all().forEach((el) => io.observe(el));

    const safety = setTimeout(() => all().forEach(reveal), 1200);
    return () => { io.disconnect(); clearTimeout(safety); };
  }, []);
}

function useCountUp(ref, finalValue, duration = 1600) {
  useEffect(() => {
    if (!ref.current) return;
    let started = false;
    const el = ref.current;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !started) {
          started = true;
          const start = performance.now();
          const tick = (now) => {
            const t = Math.min((now - start) / duration, 1);
            const eased = 1 - Math.pow(1 - t, 3);
            if (typeof finalValue === "number") {
              el.textContent = Math.round(finalValue * eased).toString();
            } else {
              el.textContent = finalValue;
              el.style.opacity = String(eased);
            }
            if (t < 1) requestAnimationFrame(tick);
          };
          if (typeof finalValue !== "number") el.style.opacity = "0";
          requestAnimationFrame(tick);
          obs.disconnect();
        }
      });
    }, { threshold: 0.5 });
    obs.observe(el);
    return () => obs.disconnect();
  }, [ref, finalValue, duration]);
}

Object.assign(window, { LiquidBackground, MagneticCursor, useSmoothScroll, useReveal, useCountUp });
