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

// ---------- Icons (inline, stroke style) ----------
const Icon = ({ name, size = 20, stroke = 1.6 }) => {
  const common = {
    width: size, height: size, viewBox: '0 0 24 24',
    fill: 'none', stroke: 'currentColor', strokeWidth: stroke,
    strokeLinecap: 'round', strokeLinejoin: 'round'
  };
  const paths = {
    arrow: <><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></>,
    check: <path d="M5 12l5 5L20 7"/>,
    plus: <><path d="M12 5v14"/><path d="M5 12h14"/></>,
    clock: <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>,
    msg: <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>,
    brain: <><path d="M12 5a3 3 0 0 0-3 3v.5A3.5 3.5 0 0 0 5.5 12 3 3 0 0 0 7 17.5 3 3 0 0 0 10 20a2 2 0 0 0 2-2V5z"/><path d="M12 5a3 3 0 0 1 3 3v.5a3.5 3.5 0 0 1 3.5 3.5 3 3 0 0 1-1.5 5.5A3 3 0 0 1 14 20a2 2 0 0 1-2-2V5z"/></>,
    receipt: <><path d="M6 3h12v18l-3-2-3 2-3-2-3 2z"/><path d="M9 8h6M9 12h6M9 16h4"/></>,
    chart: <><path d="M3 3v18h18"/><path d="M7 14l4-4 3 3 5-6"/></>,
    sparkles: <><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8"/></>,
    file: <><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6"/></>,
    chat: <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8z"/>,
    book: <><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5V4.5A2.5 2.5 0 0 1 6.5 2z"/></>,
    inbox: <><path d="M22 12h-6l-2 3h-4l-2-3H2"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></>,
    bot: <><rect x="3" y="8" width="18" height="12" rx="2"/><path d="M12 8V4M8 4h8M8 14h.01M16 14h.01M9 18h6"/></>,
    shield: <path d="M12 2 4 6v6c0 5 3.5 9 8 10 4.5-1 8-5 8-10V6z"/>,
    users: <><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></>,
    map: <><path d="M9 20 3 17V4l6 3 6-3 6 3v13l-6-3z"/><path d="M9 7v13M15 4v13"/></>,
    coin: <><circle cx="12" cy="12" r="9"/><path d="M9 9h4.5a2 2 0 0 1 0 4H9m0 0h4.5a2 2 0 0 1 0 4H9m3-8V7m0 12v-2"/></>,
    layers: <><path d="m12 2 10 6-10 6L2 8z"/><path d="m2 16 10 6 10-6"/><path d="m2 12 10 6 10-6"/></>,
    pin: <><circle cx="12" cy="10" r="3"/><path d="M12 21s-7-7-7-12a7 7 0 1 1 14 0c0 5-7 12-7 12z"/></>,
    list: <><path d="M9 6h12M9 12h12M9 18h12"/><circle cx="4" cy="6" r="1"/><circle cx="4" cy="12" r="1"/><circle cx="4" cy="18" r="1"/></>,
    eye: <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z"/><circle cx="12" cy="12" r="3"/></>,
    server: <><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><path d="M7 8h.01M7 17h.01"/></>,
    linkedin: <><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M8 10v7M8 7v.01M12 17v-4a2 2 0 1 1 4 0v4M12 13v4"/></>,
    instagram: <><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r=".5" fill="currentColor"/></>,
    youtube: <><rect x="2" y="5" width="20" height="14" rx="3"/><path d="m10 9 5 3-5 3z" fill="currentColor" stroke="none"/></>,
  };
  return <svg {...common}>{paths[name]}</svg>;
};

// ---------- Reveal on scroll ----------
function Reveal({ children, className = '', as = 'div', delay = 0 }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) { setShown(true); io.disconnect(); }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  const Tag = as;
  return (
    <Tag ref={ref} className={`reveal ${shown ? 'in' : ''} ${className}`} style={{ transitionDelay: delay + 'ms' }}>
      {children}
    </Tag>
  );
}

// ---------- Split-text headline ----------
// Optional props:
//   highlight: substring to color in brand blue (must match exactly, full words)
//   underline: single word inside the highlight (or anywhere) to underline
function SplitText({ text, as: Tag = 'h1', className = '', stagger = 40, baseDelay = 0, highlight, underline }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) { setShown(true); io.disconnect(); }
      });
    }, { threshold: 0.2 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  // Build word list with hl flag
  let segments;
  if (highlight && text.includes(highlight)) {
    const idx = text.indexOf(highlight);
    // Swallow any trailing punctuation (.,!?;:) right after the highlight so
    // it stays glued to the last highlighted word instead of becoming a
    // standalone word with a leading space.
    let endIdx = idx + highlight.length;
    while (endIdx < text.length && /[.,!?;:]/.test(text[endIdx])) endIdx++;
    segments = [
      { text: text.slice(0, idx), hl: false },
      { text: text.slice(idx, endIdx), hl: true },
      { text: text.slice(endIdx), hl: false },
    ];
  } else {
    segments = [{ text, hl: false }];
  }
  const words = [];
  segments.forEach(seg => {
    if (!seg.text) return;
    seg.text.split(' ').forEach(w => {
      if (w === '') return;
      words.push({ w, hl: seg.hl });
    });
  });

  return (
    <Tag ref={ref} className={`split ${shown ? 'in' : ''} ${className}`}>
      {words.map((tok, i) => {
        const stripped = tok.w.replace(/[.,!?;:]+$/, '');
        const isUnderlined = underline && stripped === underline;
        return (
          <span
            key={i}
            className={`split-word${tok.hl ? ' hl' : ''}`}
            style={{ transitionDelay: (baseDelay + i * stagger) + 'ms' }}
          >
            {isUnderlined ? <span className="uline">{tok.w}</span> : tok.w}
            {i < words.length - 1 ? ' ' : ''}
          </span>
        );
      })}
    </Tag>
  );
}

// ---------- Count up ----------
function CountUp({ to, suffix = '', prefix = '', duration = 1700, decimals = 0 }) {
  const ref = useRef(null);
  const [v, setV] = useState(0);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let started = false;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting && !started) {
          started = true;
          io.disconnect();
          const start = performance.now();
          const tick = (t) => {
            const p = Math.min(1, (t - start) / duration);
            const ease = 1 - Math.pow(1 - p, 3);
            setV(to * ease);
            if (p < 1) requestAnimationFrame(tick);
            else setV(to);
          };
          requestAnimationFrame(tick);
        }
      });
    }, { threshold: 0.4 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  const display = decimals > 0 ? v.toFixed(decimals) : Math.round(v).toLocaleString();
  return <span ref={ref} className="tnum">{prefix}{display}{suffix}</span>;
}

// Expose globally
Object.assign(window, { Icon, Reveal, SplitText, CountUp });
