// ESacademy — shared animation hooks & components

// ── Scroll Reveal ──────────────────────────────────────────────
function useScrollReveal({ threshold = 0.12 } = {}) {
  const ref = React.useRef(null);
  const [visible, setVisible] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      ([e]) => { if (e.isIntersecting) { setVisible(true); io.disconnect(); } },
      { threshold }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, visible];
}

function Reveal({ children, delay = 0, y = 30, style }) {
  const [ref, visible] = useScrollReveal();
  return (
    <div ref={ref} style={{
      opacity: visible ? 1 : 0,
      transform: `translateY(${visible ? 0 : y}px)`,
      transition: `opacity 0.7s ease ${delay}s, transform 0.7s cubic-bezier(0.22,0.61,0.36,1) ${delay}s`,
      ...style,
    }}>{children}</div>
  );
}

// ── Mouse Parallax (lerped for smoothness) ────────────────────
function useParallax(strength = 14) {
  const [offset, setOffset] = React.useState({ x: 0, y: 0 });
  React.useEffect(() => {
    let raf;
    let tx = 0, ty = 0;
    const onMove = (e) => {
      tx = (e.clientX / window.innerWidth - 0.5) * strength;
      ty = (e.clientY / window.innerHeight - 0.5) * strength;
    };
    const tick = () => {
      setOffset(o => {
        const nx = o.x + (tx - o.x) * 0.07;
        const ny = o.y + (ty - o.y) * 0.07;
        if (Math.abs(nx - o.x) < 0.005 && Math.abs(ny - o.y) < 0.005) return o;
        return { x: nx, y: ny };
      });
      raf = requestAnimationFrame(tick);
    };
    window.addEventListener('mousemove', onMove, { passive: true });
    raf = requestAnimationFrame(tick);
    return () => { window.removeEventListener('mousemove', onMove); cancelAnimationFrame(raf); };
  }, [strength]);
  return offset;
}

// ── Magnetic Button ───────────────────────────────────────────
function useMagnetic(strength = 0.32) {
  const ref = React.useRef(null);
  const [d, setD] = React.useState({ x: 0, y: 0 });
  const handlers = {
    onMouseMove(e) {
      const r = ref.current?.getBoundingClientRect();
      if (!r) return;
      setD({ x: (e.clientX - (r.left + r.width / 2)) * strength, y: (e.clientY - (r.top + r.height / 2)) * strength });
    },
    onMouseLeave() { setD({ x: 0, y: 0 }); },
  };
  return [ref, d, handlers];
}

// ── Card Tilt ─────────────────────────────────────────────────
function useCardTilt(maxDeg = 5) {
  const ref = React.useRef(null);
  const [t, setT] = React.useState({ rx: 0, ry: 0 });
  const handlers = {
    onMouseMove(e) {
      const r = ref.current?.getBoundingClientRect();
      if (!r) return;
      const x = (e.clientX - r.left) / r.width - 0.5;
      const y = (e.clientY - r.top) / r.height - 0.5;
      setT({ rx: -y * maxDeg, ry: x * maxDeg });
    },
    onMouseLeave() { setT({ rx: 0, ry: 0 }); },
  };
  return [ref, t, handlers];
}

// ── Cursor Aura (for dark sections) ──────────────────────────
function useCursorAura() {
  const ref = React.useRef(null);
  const [pos, setPos] = React.useState({ x: -999, y: -999, on: false });
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      setPos({ x: e.clientX - r.left, y: e.clientY - r.top, on: true });
    };
    const onLeave = () => setPos(p => ({ ...p, on: false }));
    el.addEventListener('mousemove', onMove, { passive: true });
    el.addEventListener('mouseleave', onLeave);
    return () => { el.removeEventListener('mousemove', onMove); el.removeEventListener('mouseleave', onLeave); };
  }, []);
  return [ref, pos];
}

// ── Scroll Progress (0→1 as element enters viewport) ─────────
function useScrollProgress() {
  const ref = React.useRef(null);
  const [progress, setProgress] = React.useState(0);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const root = document.getElementById('esa-a-root');
    const update = () => {
      const rect = el.getBoundingClientRect();
      const vh = window.innerHeight;
      const p = Math.min(1, Math.max(0, (vh * 0.78 - rect.top) / (rect.height * 0.35 + vh * 0.35)));
      setProgress(p);
    };
    const target = root || window;
    target.addEventListener('scroll', update, { passive: true });
    update();
    return () => target.removeEventListener('scroll', update);
  }, []);
  return [ref, progress];
}

// ── Custom Cursor ─────────────────────────────────────────────
function CustomCursor() {
  const isTouch = React.useMemo(() => window.matchMedia('(pointer: coarse)').matches, []);
  const dotRef = React.useRef(null);
  const ringRef = React.useRef(null);

  React.useEffect(() => {
    if (isTouch) return;
    let raf;
    let mx = -200, my = -200;
    let rx = -200, ry = -200;

    const onMove = (e) => {
      mx = e.clientX;
      my = e.clientY;
      const isHover = !!e.target.closest('button, a, [role="button"], input, select');
      if (ringRef.current) {
        ringRef.current.style.width = isHover ? '54px' : '36px';
        ringRef.current.style.height = isHover ? '54px' : '36px';
        ringRef.current.style.opacity = isHover ? '0.25' : '0.45';
      }
    };

    const tick = () => {
      if (dotRef.current) {
        dotRef.current.style.left = mx + 'px';
        dotRef.current.style.top = my + 'px';
      }
      rx += (mx - rx) * 0.1;
      ry += (my - ry) * 0.1;
      if (ringRef.current) {
        ringRef.current.style.left = rx + 'px';
        ringRef.current.style.top = ry + 'px';
      }
      raf = requestAnimationFrame(tick);
    };

    document.addEventListener('mousemove', onMove, { passive: true });
    raf = requestAnimationFrame(tick);
    return () => {
      document.removeEventListener('mousemove', onMove);
      cancelAnimationFrame(raf);
    };
  }, [isTouch]);

  if (isTouch) return null;

  return React.createElement(React.Fragment, null,
    React.createElement('div', { ref: dotRef, style: {
      position: 'fixed', pointerEvents: 'none', zIndex: 99999,
      width: 8, height: 8, borderRadius: '50%',
      background: '#2d4a3e', opacity: 0.85,
      transform: 'translate(-50%, -50%)',
      mixBlendMode: 'multiply', top: 0, left: 0,
    }}),
    React.createElement('div', { ref: ringRef, style: {
      position: 'fixed', pointerEvents: 'none', zIndex: 99998,
      width: 36, height: 36, borderRadius: '50%',
      border: '1.5px solid #2d4a3e', opacity: 0.45,
      transform: 'translate(-50%, -50%)',
      transition: 'width 0.3s ease, height 0.3s ease, opacity 0.3s ease',
      mixBlendMode: 'multiply', top: 0, left: 0,
    }})
  );
}

// ── Breakpoint Context ────────────────────────────────────────
const BpContext = React.createContext('desktop');

function useBreakpoint() {
  const getbp = () => {
    const w = window.innerWidth;
    return w < 640 ? 'mobile' : w < 1024 ? 'tablet' : 'desktop';
  };
  const [bp, setBp] = React.useState(getbp);
  React.useEffect(() => {
    const handler = () => setBp(getbp());
    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, []);
  return bp;
}

// ── CSS injections ─────────────────────────────────────────────
if (!document.getElementById('esa-effects-css')) {
  const s = document.createElement('style');
  s.id = 'esa-effects-css';
  s.textContent = `
    @keyframes esa-pulse-ring {
      0%   { transform: scale(1); opacity: 0.5; }
      100% { transform: scale(2.8); opacity: 0; }
    }
    @keyframes esa-fadein-page {
      from { opacity: 0; transform: translateY(18px); }
      to   { opacity: 1; transform: translateY(0); }
    }
    @keyframes esa-float {
      0%, 100% { transform: translateY(0px); }
      50%       { transform: translateY(-22px); }
    }
    @keyframes esa-carousel {
      0%   { transform: translateX(0); }
      100% { transform: translateX(-50%); }
    }
    .esa-page-enter {
      animation: esa-fadein-page 1s cubic-bezier(0.22,0.61,0.36,1) both;
    }
    .esa-page-enter-delay {
      animation: esa-fadein-page 1s cubic-bezier(0.22,0.61,0.36,1) 0.18s both;
    }
    #esa-a-root, #esa-a-root * { cursor: none !important; }
  `;
  document.head.appendChild(s);
}

Object.assign(window, {
  useScrollReveal, Reveal,
  useParallax, useMagnetic, useCardTilt,
  useCursorAura, useScrollProgress,
  CustomCursor,
  BpContext, useBreakpoint,
});
