// Inject grain texture at runtime (avoids bundler scanning url(data:...) in CSS)
(function injectGrain() {
  const c = document.createElement('canvas');
  c.width = 160; c.height = 160;
  const ctx = c.getContext('2d');
  const img = ctx.createImageData(160, 160);
  for (let i = 0; i < img.data.length; i += 4) {
    const v = (Math.random() * 255) | 0;
    img.data[i] = v; img.data[i+1] = v; img.data[i+2] = v; img.data[i+3] = 255;
  }
  ctx.putImageData(img, 0, 0);
  const url = c.toDataURL('image/png');
  const style = document.createElement('style');
  style.textContent = `.grain{background-image:url(${url})}`;
  document.head.appendChild(style);
})();

// Reveal hook. CSS defaults to visible; we arm (hide), then reveal on view.
// If anything goes wrong the element stays visible — no invisible text.
function useReveal(options = {}) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;

    // Arm: hide it (visible -> hidden via .armed class)
    el.classList.add('armed');

    const reveal = () => {
      requestAnimationFrame(() => el.classList.add('in'));
    };

    // If already in view, reveal on next frame.
    const rect = el.getBoundingClientRect();
    if (rect.top < window.innerHeight && rect.bottom > 0) {
      reveal();
      return;
    }

    let observer;
    try {
      observer = new IntersectionObserver(
        (entries) => {
          entries.forEach((e) => {
            if (e.isIntersecting) {
              reveal();
              observer.unobserve(el);
            }
          });
        },
        { threshold: options.threshold ?? 0.01, rootMargin: options.rootMargin ?? '0px 0px -40px 0px' }
      );
      observer.observe(el);
    } catch {
      reveal();
      return;
    }

    // Safety net: if somehow IO never fires within 4s, just reveal.
    const timer = setTimeout(reveal, 4000);
    return () => { clearTimeout(timer); observer && observer.disconnect(); };
  }, []);
  return ref;
}

// Reveal line (masked text that slides up)
function RevealLine({ children, delay = 0, as = 'span', className = '' }) {
  const ref = useReveal();
  const Tag = as;
  return (
    <Tag ref={ref} className={`reveal-line ${className}`}>
      <span style={{ transitionDelay: `${delay}ms` }}>{children}</span>
    </Tag>
  );
}

function FadeUp({ children, delay = 0, className = '', as = 'div' }) {
  const ref = useReveal();
  const Tag = as;
  return (
    <Tag ref={ref} className={`fade-up ${className}`} style={{ transitionDelay: `${delay}ms` }}>
      {children}
    </Tag>
  );
}

// Magnetic custom cursor (desktop / fine pointer only — touch leaves a stale emulated mouse position)
function Cursor() {
  const dotRef = React.useRef(null);
  const ringRef = React.useRef(null);
  const [useCustomCursor, setUseCustomCursor] = React.useState(() =>
    typeof window !== 'undefined' &&
    window.matchMedia('(pointer: fine) and (hover: hover)').matches
  );

  React.useEffect(() => {
    const mq = window.matchMedia('(pointer: fine) and (hover: hover)');
    const sync = () => setUseCustomCursor(mq.matches);
    sync();
    mq.addEventListener('change', sync);
    return () => mq.removeEventListener('change', sync);
  }, []);

  React.useEffect(() => {
    if (!useCustomCursor) return;
    const dot = dotRef.current;
    const ring = ringRef.current;
    if (!dot || !ring) return;

    let mx = window.innerWidth / 2, my = window.innerHeight / 2;
    let rx = mx, ry = my;
    let raf;

    const move = (e) => {
      mx = e.clientX;
      my = e.clientY;
      dot.style.transform = `translate3d(${mx}px, ${my}px, 0) translate(-50%, -50%)`;
    };

    const loop = () => {
      rx += (mx - rx) * 0.18;
      ry += (my - ry) * 0.18;
      ring.style.transform = `translate3d(${rx}px, ${ry}px, 0) translate(-50%, -50%)`;
      raf = requestAnimationFrame(loop);
    };
    loop();

    const onOver = (e) => {
      const t = e.target.closest('[data-cursor]');
      ring.classList.remove('hover', 'hover-invert');
      dot.classList.remove('hover-invert');
      if (!t) return;
      const mode = t.getAttribute('data-cursor');
      if (mode === 'invert') {
        ring.classList.add('hover-invert');
        dot.classList.add('hover-invert');
      } else {
        ring.classList.add('hover');
      }
    };

    window.addEventListener('mousemove', move);
    window.addEventListener('mouseover', onOver);
    return () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseover', onOver);
      cancelAnimationFrame(raf);
    };
  }, [useCustomCursor]);

  if (!useCustomCursor) return null;

  return (
    <>
      <div ref={ringRef} className="cursor-ring" />
      <div ref={dotRef} className="cursor-dot" />
    </>
  );
}

// Live clock
function LiveClock() {
  const [time, setTime] = React.useState('');
  React.useEffect(() => {
    const update = () => {
      const d = new Date();
      const hh = String(d.getUTCHours()).padStart(2, '0');
      const mm = String(d.getUTCMinutes()).padStart(2, '0');
      const ss = String(d.getUTCSeconds()).padStart(2, '0');
      setTime(`${hh}:${mm}:${ss} UTC`);
    };
    update();
    const id = setInterval(update, 1000);
    return () => clearInterval(id);
  }, []);
  return <span className="nav-time">{time}</span>;
}

function Nav() {
  const [menuOpen, setMenuOpen] = React.useState(false);

  React.useEffect(() => {
    const root = document.documentElement;
    if (menuOpen) root.classList.add('mobile-menu-open');
    else root.classList.remove('mobile-menu-open');
    return () => root.classList.remove('mobile-menu-open');
  }, [menuOpen]);

  const links = [
    ['01', 'Services', '#services'],
    ['02', 'Process', '#process'],
    ['03', 'Work', '#work'],
    ['04', 'Pricing', '#pricing'],
    ['05', 'FAQ', '#faq'],
    ['06', 'Contact', '#contact'],
  ];

  return (
    <>
      <nav className="nav">
        <a href="#top" className="nav-logo" data-cursor="hover">
          <svg className="nav-logo-mark" width="26" height="26" viewBox="0 0 64 64" aria-hidden="true">
            <rect width="64" height="64" rx="14" fill="#0E0E0C" />
            <path d="M16 20 L32 46 L48 20" fill="none" stroke="#F3F1EC" strokeWidth="5" strokeLinecap="round" strokeLinejoin="round" />
            <circle cx="32" cy="46" r="3.5" fill="oklch(0.72 0.18 145)" />
          </svg>
          <span>Vootlabs</span>
        </a>
        <div className="nav-links">
          <a href="#services" data-cursor="hover">Services</a>
          <a href="#process" data-cursor="hover">Process</a>
          <a href="#work" data-cursor="hover">Work</a>
          <a href="#pricing" data-cursor="hover">Pricing</a>
          <a href="#faq" data-cursor="hover">FAQ</a>
          <a href="#contact" data-cursor="hover">Contact</a>
        </div>
        <button className="mobile-menu-toggle" onClick={() => setMenuOpen(true)} aria-label="Open menu">
          <svg viewBox="0 0 16 16" fill="none">
            <path d="M2 5h12M2 11h12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
          </svg>
        </button>
      </nav>

      <div className="mobile-menu" aria-hidden={!menuOpen}>
        <button className="mobile-menu-close" onClick={() => setMenuOpen(false)} aria-label="Close menu">
          <svg viewBox="0 0 14 14" fill="none">
            <path d="M2 2L12 12M12 2L2 12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
          </svg>
        </button>
        <div className="mobile-menu-links">
          {links.map(([num, label, href]) => (
            <a key={href} href={href} onClick={() => setMenuOpen(false)}>
              <span className="num">{num}</span>
              <span>{label}</span>
            </a>
          ))}
        </div>
        <div className="mobile-menu-foot">RIYADH · DUBAI</div>
      </div>
    </>
  );
}

Object.assign(window, { useReveal, RevealLine, FadeUp, Cursor, Nav, LiveClock });
