/* OpSpot — core: reveal helpers, logo mark, sparkline, nav, footer. */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* Mark JS active so entrance animations apply (CSS keeps content visible without JS). */
if (typeof document !== 'undefined') document.documentElement.classList.add('has-js');

/* ---------- reveal-on-scroll ---------- */
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let shownT;
    const reveal = () => {
      el.classList.add('in');
      // Fallback: guarantee the end state lands even if animations are paused (capture/offscreen).
      shownT = setTimeout(() => el.classList.add('shown'), 1300);
    };
    const vh = window.innerHeight || document.documentElement.clientHeight;
    const r = el.getBoundingClientRect();
    if (r.top < vh * 0.95 && r.bottom > 0) { reveal(); return () => clearTimeout(shownT); }
    const safety = setTimeout(reveal, 2600);
    let io;
    if ('IntersectionObserver' in window) {
      io = new IntersectionObserver((entries) => {
        entries.forEach(e => {
          if (e.isIntersecting) { reveal(); io.unobserve(el); clearTimeout(safety); }
        });
      }, { threshold: 0.08, rootMargin: '0px 0px -8% 0px' });
      io.observe(el);
    } else { reveal(); }
    return () => { clearTimeout(safety); clearTimeout(shownT); if (io) io.disconnect(); };
  }, []);
  return ref;
}

function Reveal({ as: Tag = 'div', delay = 0, className = '', children, ...rest }) {
  const ref = useReveal();
  const d = delay ? ` d${delay}` : '';
  return <Tag ref={ref} className={`reveal${d} ${className}`} {...rest}>{children}</Tag>;
}

/* ---------- count-up number ---------- */
function useCountUp(target, run, dur = 1100) {
  const [n, setN] = useState(0);
  useEffect(() => {
    if (!run) return;
    let raf, start;
    const tick = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      setN(Math.round(target * eased));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    // Fallback: ensure the final value lands even if rAF is paused (offscreen / capture).
    const fallback = setTimeout(() => setN(target), dur + 250);
    return () => { cancelAnimationFrame(raf); clearTimeout(fallback); };
  }, [target, run, dur]);
  return n;
}

function CountMoney({ value, prefix = '$', run = true }) {
  const n = useCountUp(value, run);
  return <span>{prefix}{n.toLocaleString()}</span>;
}

/* ---------- logo mark ---------- */
function OpSpotMark({ size = 30 }) {
  const positions = [
    { x: 50, y: 14, kind: 'a' }, { x: 86, y: 50, kind: 'a' },
    { x: 50, y: 86, kind: 'a' }, { x: 14, y: 50, kind: 'a' },
    { x: 75.5, y: 24.5, kind: 'b' }, { x: 75.5, y: 75.5, kind: 'b' },
    { x: 24.5, y: 75.5, kind: 'b' }, { x: 24.5, y: 24.5, kind: 'b' },
  ];
  const orange = '#ED7B1C', tan = '#F5C28A', brown = '#7D2F17', bg = '#fafaf7';
  return (
    <svg width={size} height={size} viewBox="0 0 100 100" aria-hidden="true" className="opspot-mark">
      {positions.map((p, i) => (
        <line key={i} x1="50" y1="50" x2={p.x} y2={p.y}
              stroke={tan} strokeWidth="1.4" strokeDasharray="2 2.4" strokeLinecap="round" />
      ))}
      <circle cx="50" cy="50" r="12" fill={brown} />
      {positions.map((p, i) => {
        const c = p.kind === 'a' ? orange : tan;
        return (
          <g key={`n${i}`}>
            <circle cx={p.x} cy={p.y} r="6.5" fill={bg} stroke={c} strokeWidth="1.6" />
            <circle cx={p.x} cy={p.y} r="2.8" fill={c} />
          </g>
        );
      })}
    </svg>
  );
}

/* ---------- sparkline ---------- */
function Spark({ seed = 1, color = 'var(--violet)' }) {
  const pts = useMemo(() => {
    const arr = []; let v = 28;
    for (let i = 0; i < 24; i++) {
      v += (Math.sin(i * 1.3 + seed) + Math.cos(i * 0.7 + seed * 2)) * 4 + (i * 0.3);
      arr.push(Math.max(4, Math.min(40, v)));
    }
    return arr;
  }, [seed]);
  const path = pts.map((y, i) => `${i === 0 ? 'M' : 'L'} ${(i / (pts.length - 1)) * 100} ${44 - y}`).join(' ');
  return (
    <svg viewBox="0 0 100 44" preserveAspectRatio="none">
      <defs>
        <linearGradient id={`sp${seed}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" stopColor={color} stopOpacity="0.5" />
          <stop offset="1" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={path + ` L 100 44 L 0 44 Z`} fill={`url(#sp${seed})`} />
      <path d={path} fill="none" stroke={color} strokeWidth="1.2" strokeLinecap="round" />
    </svg>
  );
}

/* scroll helper */
function scrollToId(id) {
  const el = document.getElementById(id);
  if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 70, behavior: 'smooth' });
}

/* ---------- Nav ---------- */
function Nav({ onPricing, onImplementation }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const on = () => setScrolled(window.scrollY > 8);
    on(); window.addEventListener('scroll', on, { passive: true });
    return () => window.removeEventListener('scroll', on);
  }, []);
  return (
    <nav className={`nav ${scrolled ? 'is-scrolled' : ''}`}>
      <div className="nav-inner">
        <a href="#top" className="brand" onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}>
          <OpSpotMark size={30} />
          <span>OpSpot</span>
        </a>
        <div className="nav-links">
          <a href="#leak" onClick={(e) => { e.preventDefault(); scrollToId('leak'); }}>The leak</a>
          <a href="#pricing" onClick={(e) => { e.preventDefault(); onPricing && onPricing(); }}>Pricing</a>
          <a href="#implementation" onClick={(e) => { e.preventDefault(); onImplementation && onImplementation(); }}>Implementation</a>
          <a href="#trust" onClick={(e) => { e.preventDefault(); scrollToId('trust'); }}>Receipts</a>
        </div>
        <div className="nav-spacer" />
        <div className="nav-cta">
          <a href={CAL} target="_blank" rel="noopener" className="btn btn-ghost nav-call">Book a call</a>
          <a href="#contact" className="btn btn-primary" onClick={(e) => { e.preventDefault(); scrollToId('contact'); }}>Get my free audit</a>
        </div>
      </div>
    </nav>
  );
}

/* ---------- Footer ---------- */
function Footer() {
  return (
    <footer className="footer">
      <div className="footer-inner">
        <a href="#top" className="brand" onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}>
          <OpSpotMark size={26} />
          <span>OpSpot</span>
        </a>
        <span className="foot-meta">opspot.ai · AI employees for operational ROI · Wilmington-built · 2026</span>
        <div className="links">
          <a href="#contact" onClick={(e) => { e.preventDefault(); scrollToId('contact'); }}>Get my free audit</a>
          <a href="mailto:hello@opspot.ai">hello@opspot.ai</a>
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, { useReveal, Reveal, useCountUp, CountMoney, OpSpotMark, Spark, scrollToId, Nav, Footer });
