// utils.jsx — Shared hooks, MolecularCanvas, Cursor

const { useState, useEffect, useRef } = React;

/* ── useScrollReveal ── */
function useScrollReveal(opts = {}) {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setVisible(true); obs.disconnect(); }
    }, { threshold: opts.threshold ?? 0.12, rootMargin: opts.margin ?? '-40px 0px' });
    obs.observe(el);
    return () => obs.disconnect();
  }, []);
  return [ref, visible];
}

/* ── useCountUp ── */
function useCountUp(target, duration = 1800, active = false) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    if (!active) return;
    const num = parseInt(String(target).replace(/\D/g, ''));
    const start = performance.now();
    const tick = (now) => {
      const p = Math.min((now - start) / duration, 1);
      const eased = 1 - Math.pow(1 - p, 3);
      setCount(Math.floor(eased * num));
      if (p < 1) requestAnimationFrame(tick); else setCount(num);
    };
    requestAnimationFrame(tick);
  }, [active, target, duration]);
  return count;
}

/* ── MolecularCanvas ── */
function MolecularCanvas({ style, className }) {
  const canvasRef = useRef(null);
  useEffect(() => {
    const canvas = canvasRef.current; if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let particles = [], animId, mouseX = -999, mouseY = -999;

    const resize = () => {
      canvas.width = canvas.offsetWidth;
      canvas.height = canvas.offsetHeight;
      particles = Array.from({ length: 62 }, () => ({
        x: Math.random() * canvas.width,
        y: Math.random() * canvas.height,
        vx: (Math.random() - 0.5) * 0.45,
        vy: (Math.random() - 0.5) * 0.45,
        r: Math.random() * 1.6 + 0.8,
      }));
    };

    const draw = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (let i = 0; i < particles.length; i++) {
        for (let j = i + 1; j < particles.length; j++) {
          const dx = particles[i].x - particles[j].x;
          const dy = particles[i].y - particles[j].y;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < 125) {
            ctx.beginPath();
            ctx.moveTo(particles[i].x, particles[i].y);
            ctx.lineTo(particles[j].x, particles[j].y);
            ctx.strokeStyle = `rgba(38,74,49,${0.13 * (1 - d / 125)})`;
            ctx.lineWidth = 1;
            ctx.stroke();
          }
        }
      }
      particles.forEach(p => {
        const dx = p.x - mouseX, dy = p.y - mouseY;
        const d = Math.sqrt(dx * dx + dy * dy);
        if (d < 85) { p.vx += (dx / d) * 0.055; p.vy += (dy / d) * 0.055; }
        const spd = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
        if (spd > 1.7) { p.vx = (p.vx / spd) * 1.7; p.vy = (p.vy / spd) * 1.7; }
        p.vx *= 0.999; p.vy *= 0.999;
        p.x += p.vx; p.y += p.vy;
        if (p.x < 0) p.x = canvas.width; if (p.x > canvas.width) p.x = 0;
        if (p.y < 0) p.y = canvas.height; if (p.y > canvas.height) p.y = 0;
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
        ctx.fillStyle = 'rgba(255,255,255,0.17)';
        ctx.fill();
      });
    };

    const animate = () => { draw(); animId = requestAnimationFrame(animate); };
    const onMM = (e) => {
      const r = canvas.getBoundingClientRect();
      mouseX = e.clientX - r.left; mouseY = e.clientY - r.top;
    };
    window.addEventListener('resize', resize);
    canvas.addEventListener('mousemove', onMM);
    resize(); animate();
    return () => {
      cancelAnimationFrame(animId);
      window.removeEventListener('resize', resize);
      canvas.removeEventListener('mousemove', onMM);
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', ...style }}
      className={className}
    />
  );
}

/* ── Custom Cursor (desktop only) ── */
function Cursor() {
  const dotRef = useRef(null);
  const ringRef = useRef(null);
  const mouse = useRef({ x: 0, y: 0 });
  const lag = useRef({ x: 0, y: 0 });

  useEffect(() => {
    if (window.innerWidth < 1024) return;
    const dot = dotRef.current, ring = ringRef.current;
    let frame;

    const onMove = (e) => { mouse.current = { x: e.clientX, y: e.clientY }; };
    const onOver = (e) => {
      if (e.target.closest('a,button,[data-hover]')) {
        dot.style.transform = 'translate(-50%,-50%) scale(0)';
        ring.style.width = ring.style.height = '42px';
        ring.style.background = 'transparent';
        ring.style.border = '2px solid #264A31';
      }
    };
    const onOut = (e) => {
      if (e.target.closest('a,button,[data-hover]')) {
        dot.style.transform = 'translate(-50%,-50%) scale(1)';
        ring.style.width = ring.style.height = '12px';
        ring.style.background = '#264A31';
        ring.style.border = '2px solid #264A31';
      }
    };

    const animate = () => {
      lag.current.x += (mouse.current.x - lag.current.x) * 0.11;
      lag.current.y += (mouse.current.y - lag.current.y) * 0.11;
      if (dot) { dot.style.left = mouse.current.x + 'px'; dot.style.top = mouse.current.y + 'px'; }
      if (ring) { ring.style.left = lag.current.x + 'px'; ring.style.top = lag.current.y + 'px'; }
      frame = requestAnimationFrame(animate);
    };

    document.addEventListener('mousemove', onMove);
    document.addEventListener('mouseover', onOver);
    document.addEventListener('mouseout', onOut);
    animate();
    return () => {
      cancelAnimationFrame(frame);
      document.removeEventListener('mousemove', onMove);
      document.removeEventListener('mouseover', onOver);
      document.removeEventListener('mouseout', onOut);
    };
  }, []);

  return (
    <>
      <div ref={dotRef} style={{
        position: 'fixed', width: 12, height: 12, borderRadius: '50%',
        background: '#264A31', pointerEvents: 'none', zIndex: 99999,
        transform: 'translate(-50%,-50%)', left: 0, top: 0,
        transition: 'transform 0.18s ease',
      }} />
      <div ref={ringRef} style={{
        position: 'fixed', width: 12, height: 12, borderRadius: '50%',
        background: '#264A31', border: '2px solid #264A31',
        pointerEvents: 'none', zIndex: 99998,
        transform: 'translate(-50%,-50%)', left: 0, top: 0,
        transition: 'width 0.25s ease, height 0.25s ease, background 0.25s ease, border 0.25s ease',
      }} />
    </>
  );
}

/* ── Logo source passthrough — logo.png / logo-white.png already ship with transparent backgrounds ── */
function useRemoveBg(src) {
  return src;
}

Object.assign(window, { useScrollReveal, useCountUp, MolecularCanvas, Cursor, useRemoveBg });
