// Shared primitives & icons
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// Intersection observer hook for scroll reveal
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          el.classList.add('in');
          io.unobserve(el);
        }
      });
    }, { threshold: 0.12 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return ref;
}

// Count-up hook
function useCountUp(target, { duration = 1800, start = 0, decimals = 0 } = {}) {
  const [v, setV] = useState(start);
  const ref = useRef(null);
  const started = useRef(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting && !started.current) {
          started.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);
            setV(start + (target - start) * eased);
            if (p < 1) requestAnimationFrame(tick);
          };
          requestAnimationFrame(tick);
        }
      });
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, [target]);
  return [ref, decimals ? v.toFixed(decimals) : Math.round(v)];
}

// Tiny inline icon set (stroke, 20px)
const Icon = ({ name, size = 18, stroke = 1.5, className = '' }) => {
  const common = {
    width: size, height: size, viewBox: '0 0 24 24',
    fill: 'none', stroke: 'currentColor', strokeWidth: stroke,
    strokeLinecap: 'round', strokeLinejoin: 'round', className
  };
  const paths = {
    arrow: <path d="M5 12h14M13 6l6 6-6 6" />,
    arrowup: <path d="M7 17L17 7M7 7h10v10" />,
    arrowdown: <path d="M7 7l10 10M17 7v10H7" />,
    plus: <path d="M12 5v14M5 12h14" />,
    minus: <path d="M5 12h14" />,
    check: <path d="M5 12l4 4 10-10" />,
    chev: <path d="M9 6l6 6-6 6" />,
    globe: <><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 010 18M12 3a14 14 0 000 18"/></>,
    search: <><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></>,
    target: <><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1"/></>,
    megaphone: <path d="M3 10v4l14 4V6L3 10zM17 8v8M7 14l1 5h3l-1-5"/>,
    code: <path d="M8 6l-5 6 5 6M16 6l5 6-5 6"/>,
    server: <><rect x="3" y="4" width="18" height="7" rx="1.5"/><rect x="3" y="13" width="18" height="7" rx="1.5"/><circle cx="7" cy="7.5" r=".5" fill="currentColor"/><circle cx="7" cy="16.5" r=".5" fill="currentColor"/></>,
    spark: <path d="M12 3l2 6 6 2-6 2-2 6-2-6-6-2 6-2z"/>,
    device: <><rect x="5" y="3" width="14" height="18" rx="2"/><path d="M11 17h2"/></>,
    browser: <><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 9h18M7 6.5h.01M10 6.5h.01"/></>,
    pen: <path d="M12 20h9M16 3.5a2.1 2.1 0 013 3L7 19l-4 1 1-4L16 3.5z"/>,
    mail: <><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></>,
    phone: <path d="M22 16v3a2 2 0 01-2 2A18 18 0 013 5a2 2 0 012-2h3l2 5-2 1a12 12 0 006 6l1-2 5 2z"/>,
    play: <path d="M8 5v14l11-7z" fill="currentColor" stroke="none"/>,
    sparkles: <><path d="M5 3v4M3 5h4M19 13v4M17 15h4"/><path d="M12 5l2.2 5.8L20 13l-5.8 2.2L12 21l-2.2-5.8L4 13l5.8-2.2L12 5z"/></>,
    chart: <path d="M4 20V10M10 20V4M16 20v-8M22 20H2"/>,
    zap: <path d="M13 2L3 14h8l-1 8 10-12h-8l1-8z"/>,
    ext: <path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6M15 3h6v6M21 3l-9 9"/>,
    close: <path d="M6 6l12 12M18 6L6 18"/>
  };
  return <svg {...common}>{paths[name]}</svg>;
};

// Noise-free SVG sparkline
const Sparkline = ({ data = [], width = 120, height = 32, color = 'var(--accent)' }) => {
  if (!data.length) return null;
  const max = Math.max(...data), min = Math.min(...data);
  const range = max - min || 1;
  const step = width / (data.length - 1);
  const pts = data.map((v, i) => [i * step, height - ((v - min) / range) * height]);
  const d = pts.map((p, i) => (i ? 'L' : 'M') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');
  const fill = d + ` L ${width} ${height} L 0 ${height} Z`;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
      <path d={fill} fill={color} opacity="0.1" />
      <path d={d} fill="none" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
};

// Logo mark — wordmark only (icon hidden)
const Logo = ({ size = 28 }) => (
  <div style={{ display:'flex', alignItems:'center', gap: 10 }}>
    <div style={{ fontWeight: 600, letterSpacing: '-0.02em', fontSize: 16 }}>theprofit<span style={{opacity:.55}}>platform</span></div>
  </div>
);

// Media query hook — subscribes to viewport changes, returns boolean match.
function useMediaQuery(query) {
  const get = () => typeof window !== 'undefined' && window.matchMedia(query).matches;
  const [matches, setMatches] = useState(get);
  useEffect(() => {
    const mql = window.matchMedia(query);
    const onChange = () => setMatches(mql.matches);
    onChange();
    mql.addEventListener('change', onChange);
    return () => mql.removeEventListener('change', onChange);
  }, [query]);
  return matches;
}
const useIsMobile = () => useMediaQuery('(max-width: 640px)');
const useIsTablet = () => useMediaQuery('(max-width: 1024px)');

Object.assign(window, { useReveal, useCountUp, Icon, Sparkline, Logo, useMediaQuery, useIsMobile, useIsTablet });
