// 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 = () => (
  <a className="logo" aria-label="HiLooks · heating">
    <span className="logo-mark logo-mark-photo" aria-hidden="true">
      <img src="hilooks-mark-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 }) => (
  <div className="tab-group">
    <button className={mode === 'home' ? 'active' : ''} onClick={() => setMode('home')}>Homeowners</button>
    <button className={mode === 'eng' ? 'active' : ''} onClick={() => setMode('eng')}>Engineers</button>
  </div>
);

const Header = ({ mode, setMode }) => {
  const links = mode === 'home'
    ? ['How it works', 'Savings', 'Finance', 'Stories', 'About']
    : ['Partner', 'Academy', 'Tiers', 'Rates', 'Portal', 'Apply'];
  return (
    <header className="header">
      <div className="container header-inner">
        <Logo />
        <ModeTabs mode={mode} setMode={setMode} />
        <nav className="nav-links" style={{ justifyContent: 'flex-end', alignItems: 'center' }}>
          {links.map(l => <a key={l}>{l}</a>)}
          <a className="btn btn-accent btn-sm">
            {mode === 'home' ? 'Get a quote' : 'Apply to join'} <span className="arrow">→</span>
          </a>
        </nav>
      </div>
    </header>
  );
};

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 ANVUL LTD · CH 17111703 · OPERATED AS HILOOKS UNDER LICENCE</span>
        <span>HILOOKS.UK · MCS NIC · PROVISIONAL · MADE IN BRITAIN</span>
      </div>
      <div style={{
        marginTop: 12,
        fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--fg-4)', letterSpacing: '0.08em', lineHeight: 1.6, maxWidth: 880,
      }}>
        All source, design and product IP owned by Anvul Ltd · 16 Radford Road, Stoke-on-Trent, ST4 7DA, United Kingdom. The HiLooks trading name and consumer-facing brand are operated under a non-transferable licence from Anvul Ltd.
      </div>
    </div>
  </footer>
);

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