/* global React */
const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* ============================================
   Shared primitives
   ============================================ */

// Magnetic hover effect — pulls the element toward cursor
function useMagnetic(strength = 0.35) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf;
    const move = (e) => {
      const r = el.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height / 2;
      const dx = (e.clientX - cx) * strength;
      const dy = (e.clientY - cy) * strength;
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        el.style.transform = `translate(${dx}px, ${dy}px)`;
      });
    };
    const leave = () => {
      cancelAnimationFrame(raf);
      el.style.transform = '';
    };
    el.addEventListener('mousemove', move);
    el.addEventListener('mouseleave', leave);
    return () => {
      el.removeEventListener('mousemove', move);
      el.removeEventListener('mouseleave', leave);
      cancelAnimationFrame(raf);
    };
  }, [strength]);
  return ref;
}

// Reveal-on-scroll
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal:not(.is-in)');
    if (!('IntersectionObserver' in window)) {
      els.forEach((el) => el.classList.add('is-in'));
      return;
    }
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            e.target.classList.add('is-in');
            io.unobserve(e.target);
          }
        });
      },
      { threshold: 0.12, rootMargin: '0px 0px -8% 0px' }
    );
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  });
}

// Count-up
function useCountUp(target, { duration = 1800, start = 0 } = {}) {
  const [val, setVal] = useState(start);
  const ref = useRef(null);
  const triggered = useRef(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting && !triggered.current) {
            triggered.current = true;
            const t0 = performance.now();
            const tick = (now) => {
              const p = Math.min(1, (now - t0) / duration);
              const eased = 1 - Math.pow(1 - p, 3);
              setVal(Math.round(start + (target - start) * eased));
              if (p < 1) requestAnimationFrame(tick);
            };
            requestAnimationFrame(tick);
          }
        });
      },
      { threshold: 0.3 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [target, duration, start]);
  return [val, ref];
}

// Arrow icon
const Arrow = ({ className = '' }) => (
  <svg className={className} width="14" height="14" viewBox="0 0 14 14" fill="none">
    <path d="M2 7H12M12 7L8 3M12 7L8 11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
  </svg>
);

const Plus = ({ className = '', size = 14 }) => (
  <svg className={className} width={size} height={size} viewBox="0 0 14 14" fill="none">
    <path d="M7 2V12M2 7H12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
  </svg>
);

const Close = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 14 14" fill="none">
    <path d="M3 3L11 11M11 3L3 11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
  </svg>
);

/* ============================================
   Loader / Cursor / ScrollProgress / Nav
   ============================================ */

function Loader() {
  const [pct, setPct] = useState(0);
  const [hidden, setHidden] = useState(false);
  useEffect(() => {
    let p = 0;
    const id = setInterval(() => {
      p += Math.random() * 12 + 4;
      if (p >= 100) {
        p = 100;
        setPct(100);
        clearInterval(id);
        setTimeout(() => setHidden(true), 600);
      } else {
        setPct(p);
      }
    }, 120);
    return () => clearInterval(id);
  }, []);
  return (
    <div className={`loader ${hidden ? 'is-hidden' : ''}`}>
      <div className="loader-mark">ashma maharjan</div>
      <div className="loader-bar">
        <div className="loader-bar-fill" style={{ transform: `scaleX(${pct/100})` }} />
      </div>
      <div className="loader-percent">{String(Math.round(pct)).padStart(3, '0')} / 100</div>
    </div>
  );
}

function Cursor() {
  const dotRef = useRef(null);
  const ringRef = useRef(null);
  useEffect(() => {
    if (!window.matchMedia('(hover: hover) and (pointer: fine)').matches) return;
    let dx = 0, dy = 0, rx = 0, ry = 0, mx = 0, my = 0;
    const onMove = (e) => { mx = e.clientX; my = e.clientY; };
    const onDown = () => ringRef.current?.classList.add('is-click');
    const onUp = () => ringRef.current?.classList.remove('is-click');
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mousedown', onDown);
    window.addEventListener('mouseup', onUp);

    // hover detect
    const hovers = () => document.querySelectorAll('a, button, .cursor-target, input, textarea');
    let nodes = hovers();
    const enter = () => ringRef.current?.classList.add('is-hover');
    const leave = () => ringRef.current?.classList.remove('is-hover');
    const wire = () => {
      nodes.forEach((n) => { n.addEventListener('mouseenter', enter); n.addEventListener('mouseleave', leave); });
    };
    wire();
    const mo = new MutationObserver(() => {
      nodes.forEach((n) => { n.removeEventListener('mouseenter', enter); n.removeEventListener('mouseleave', leave); });
      nodes = hovers();
      wire();
    });
    mo.observe(document.body, { childList: true, subtree: true });

    let raf;
    const tick = () => {
      dx += (mx - dx) * 0.6;
      dy += (my - dy) * 0.6;
      rx += (mx - rx) * 0.15;
      ry += (my - ry) * 0.15;
      if (dotRef.current) dotRef.current.style.transform = `translate(${dx}px, ${dy}px) translate(-50%, -50%)`;
      if (ringRef.current) ringRef.current.style.transform = `translate(${rx}px, ${ry}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mousedown', onDown);
      window.removeEventListener('mouseup', onUp);
      mo.disconnect();
    };
  }, []);
  return (
    <>
      <div className="cursor-dot" ref={dotRef} />
      <div className="cursor-ring" ref={ringRef} />
    </>
  );
}

function ScrollProgress() {
  const ref = useRef(null);
  useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      const p = max > 0 ? window.scrollY / max : 0;
      if (ref.current) ref.current.style.transform = `scaleX(${p})`;
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <div className="scroll-progress">
      <div className="scroll-progress-fill" ref={ref} />
    </div>
  );
}

function Nav() {
  const [active, setActive] = useState('home');
  useEffect(() => {
    const ids = ['home', 'about', 'skills', 'projects', 'experience', 'voices', 'contact'];
    const sections = ids.map((id) => document.getElementById(id)).filter(Boolean);
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) setActive(e.target.id);
        });
      },
      { rootMargin: '-40% 0px -55% 0px' }
    );
    sections.forEach((s) => io.observe(s));
    return () => io.disconnect();
  }, []);
  const items = [
    { id: 'home', label: 'Index' },
    { id: 'about', label: 'About' },
    { id: 'skills', label: 'Stack' },
    { id: 'projects', label: 'Work' },
    { id: 'experience', label: 'Journey' },
    { id: 'voices', label: 'Voices' },
  ];
  const go = (id) => (e) => {
    e.preventDefault();
    const el = document.getElementById(id);
    if (!el) return;
    const top = el.getBoundingClientRect().top + window.scrollY - 12;
    if (window.__lenis) {
      window.__lenis.scrollTo(top, { duration: 1.4 });
    } else {
      window.scrollTo({ top, behavior: 'smooth' });
    }
  };
  return (
    <nav className="nav">
      <a href="#home" className="nav-brand" onClick={go('home')}>
        <span className="brand-mark">AM</span>
        <span className="brand-name">ashma maharjan<span className="dot">.</span></span>
      </a>
      <div className="nav-links">
        {items.slice(1).map((i) => (
          <a key={i.id} href={`#${i.id}`} onClick={go(i.id)}
             className={`nav-link ${active === i.id ? 'active' : ''}`}>
            {i.label}
          </a>
        ))}
      </div>
      <a href="#contact" className="nav-cta" onClick={go('contact')}>
        Let's talk <Arrow />
      </a>
    </nav>
  );
}

Object.assign(window, { useMagnetic, useReveal, useCountUp, Arrow, Plus, Close, Loader, Cursor, ScrollProgress, Nav });
