// Shared primitives: scroll, reveal, magnetic, header, footer

const useReveal = (opts = {}) => {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    const r = ref.current.getBoundingClientRect();
    if (r.top < window.innerHeight && r.bottom > 0) { setShown(true); return; }
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setShown(true); obs.disconnect(); }
    }, { threshold: 0.05 });
    obs.observe(ref.current);
    const fb = setTimeout(() => setShown(true), 300);
    return () => { obs.disconnect(); clearTimeout(fb); };
  }, []);
  return [ref, shown];
};

const Reveal = ({ children, delay = 0, as: T = 'div', style, className = '', ...rest }) => {
  const [ref, shown] = useReveal();
  return <T ref={ref} className={`reveal ${shown ? 'in' : ''} ${className}`}
    style={{ transitionDelay: `${delay}ms`, ...style }} {...rest}>{children}</T>;
};

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

const useScrollProgress = (ref) => {
  const [p, setP] = React.useState(0);
  React.useEffect(() => {
    const on = () => {
      if (!ref.current) return;
      const r = ref.current.getBoundingClientRect();
      const vh = window.innerHeight;
      const total = r.height + vh;
      const seen = vh - r.top;
      setP(Math.max(0, Math.min(1, seen / total)));
    };
    window.addEventListener('scroll', on, { passive: true });
    on();
    return () => window.removeEventListener('scroll', on);
  }, [ref]);
  return p;
};

const CountUp = ({ to, duration = 1400, prefix = '', suffix = '', decimals = 0 }) => {
  const [ref, shown] = useReveal();
  const [v, setV] = React.useState(0);
  React.useEffect(() => {
    if (!shown) return;
    const start = performance.now();
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const e = 1 - Math.pow(1 - p, 3);
      setV(to * e);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [shown, to, duration]);
  return <span ref={ref} className="tnum">{prefix}{v.toFixed(decimals)}{suffix}</span>;
};

const Logo = () => {
  const goTop = (e) => {
    e.preventDefault();
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };
  return (
    <a className="logo" href="#top" onClick={goTop} aria-label="HiLooks · heating · back to top">
      <span className="logo-mark logo-mark-photo" aria-hidden="true">
        <img src="hilooks-mark-cut-512.png" alt="" loading="eager" />
      </span>
      <span className="logo-mark logo-mark-svg" aria-hidden="true">
        <svg viewBox="0 0 32 32" fill="none">
          <path d="M5 22 Q16 8 27 22" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
          <path d="M8 25 Q16 14.5 24 25" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" opacity="0.6" />
          <path d="M11 28 Q16 22 21 28" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" opacity="0.32" />
          <circle cx="16" cy="17" r="1.4" fill="currentColor" />
        </svg>
      </span>
      <span className="logo-word">HiLooks</span>
      <span className="logo-tag">heating</span>
    </a>
  );
};

const ModeTabs = ({ mode, setMode, className = '' }) => (
  <div className={`tab-group ${className}`.trim()}>
    <button className={mode === 'home' ? 'active' : ''} onClick={() => setMode('home')}>Homeowners</button>
    <button className={mode === 'eng' ? 'active' : ''} onClick={() => setMode('eng')}>Engineers</button>
  </div>
);

const NavDrawer = ({ open, onClose, mode, setMode, links, ctaHref, ctaLabel }) => {
  React.useEffect(() => {
    if (!open) return;
    const esc = (e) => { if (e.key === 'Escape') onClose(); };
    document.body.classList.add('drawer-open');
    window.addEventListener('keydown', esc);
    return () => {
      document.body.classList.remove('drawer-open');
      window.removeEventListener('keydown', esc);
    };
  }, [open, onClose]);

  if (!open) return null;
  const handleLinkClick = () => {
    // Close drawer after the click event finishes so the anchor scroll fires.
    setTimeout(onClose, 50);
  };
  return (
    <div className="nav-drawer-overlay" onClick={onClose}>
      <aside className="nav-drawer" onClick={(e) => e.stopPropagation()} role="dialog" aria-label="Navigation">
        <div className="nav-drawer-head">
          <Logo />
          <button className="nav-drawer-close" onClick={onClose} aria-label="Close menu">×</button>
        </div>
        <ModeTabs mode={mode} setMode={setMode} className="mode-tabs-drawer" />
        <nav className="nav-drawer-links">
          {links.map(([label, href]) => (
            <a key={label} href={href} onClick={handleLinkClick}>
              <span>{label}</span>
              <span className="nav-drawer-arrow">→</span>
            </a>
          ))}
        </nav>
        <a className="btn btn-accent nav-drawer-cta" href={ctaHref} onClick={handleLinkClick}>
          {ctaLabel} <span className="arrow">→</span>
        </a>
        <div className="nav-drawer-foot">
          <span>HILOOKS.UK</span>
          <span>· DERBY · NOTTS · SHEFFIELD</span>
        </div>
      </aside>
    </div>
  );
};

const Header = ({ mode, setMode }) => {
  const [navOpen, setNavOpen] = React.useState(false);
  const links = mode === 'home'
    ? [['How it works','#how'], ['Savings','#savings'], ['Finance','#finance'], ['Stories','#stories'], ['About','#about']]
    : [['Partner','#partner'], ['Academy','#academy'], ['Tiers','#tiers'], ['Rates','#rates'], ['Portal','#portal'], ['Apply','#apply']];
  const ctaHref = mode === 'home' ? '#savings' : '#apply';
  const ctaLabel = mode === 'home' ? 'Get a quote' : 'Apply to join';
  return (
    <>
      <header className="header">
        <div className="container header-row1">
          <Logo />
          <nav className="nav-links nav-links-desktop">
            {links.map(([l, h]) => <a key={l} href={h}>{l}</a>)}
          </nav>
          <ModeTabs mode={mode} setMode={setMode} className="mode-tabs-desktop" />
          <a className="btn btn-accent btn-sm header-cta" href={ctaHref}>
            {ctaLabel} <span className="arrow">→</span>
          </a>
          <button className="nav-burger" onClick={() => setNavOpen(true)} aria-label="Open menu">
            <span /><span /><span />
          </button>
        </div>
        <div className="container header-row2">
          <ModeTabs mode={mode} setMode={setMode} className="mode-tabs-mobile" />
        </div>
      </header>
      <NavDrawer
        open={navOpen}
        onClose={() => setNavOpen(false)}
        mode={mode}
        setMode={(m) => { setMode(m); }}
        links={links}
        ctaHref={ctaHref}
        ctaLabel={ctaLabel}
      />
    </>
  );
};

const Footer = () => (
  <footer style={{ borderTop: '1px solid var(--line)', padding: '80px 0 40px', marginTop: 80 }}>
    <div className="container">
      <div style={{ display: 'grid', gridTemplateColumns: '1.6fr 1fr 1fr 1fr', gap: 48 }}>
        <div>
          <Logo />
          <p style={{ marginTop: 20, color: 'var(--fg-3)', fontSize: 14, maxWidth: 300, lineHeight: 1.6 }}>
            Heat pump installations, engineered properly. MCS-certified, manufacturer-trained, obsessive about details.
          </p>
          <div style={{ marginTop: 24, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            {['MCS', 'HIES', 'TrustMark', 'NICEIC', 'Daikin D1+', 'Vaillant'].map(b => (
              <span key={b} className="chip" style={{ fontSize: 10, letterSpacing: '0.1em' }}>{b}</span>
            ))}
          </div>
        </div>
        {[
          { h: 'Customers', l: ['Get a quote', 'BUS grant', 'Finance', 'Aftercare', 'Reviews'] },
          { h: 'Partners', l: ['Partner network', 'Academy', 'Tier ladder', 'Rate card', 'Apply to join'] },
          { h: 'Company', l: ['About', 'Careers', 'Press', 'Contact', 'Privacy'] },
        ].map(c => (
          <div key={c.h}>
            <div className="mono" style={{ fontSize: 11, color: 'var(--fg-4)', letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 16 }}>{c.h}</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              {c.l.map(li => <a key={li} style={{ fontSize: 14, color: 'var(--fg-2)' }}>{li}</a>)}
            </div>
          </div>
        ))}
      </div>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 16,
        marginTop: 64, paddingTop: 24, borderTop: '1px solid var(--line)',
        fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--fg-4)', letterSpacing: '0.06em',
      }}>
        <span>© 2026 HILOOKS · HEAT PUMPS, ENGINEERED PROPERLY</span>
        <span>HILOOKS.UK · MCS NIC · PROVISIONAL · MADE IN BRITAIN</span>
      </div>
    </div>
  </footer>
);

Object.assign(window, { useReveal, Reveal, ScrollProgress, useScrollProgress, CountUp, Logo, Header, Footer, ModeTabs });
