/* ============================================================
   VELOX AI — icons + shared UI helpers  → window
   Minimal geometric line icons built from primitives.
   Visibility engine is scroll-based (IntersectionObserver is
   unreliable in the preview sandbox).
   ============================================================ */
const { useState, useEffect, useRef, useCallback } = React;

const ST = { fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" };

/* ---------- scroll-based visibility engine ---------- */
const _watchers = new Set();
let _wired = false;
function _run() { _watchers.forEach((fn) => fn()); }
function _wire() {
  if (_wired) return; _wired = true;
  window.addEventListener("scroll", _run, { passive: true });
  window.addEventListener("resize", _run);
}
function onScrollCheck(fn) { _wire(); _watchers.add(fn); fn(); return () => _watchers.delete(fn); }
function isInView(el, frac = 0.85) {
  if (!el) return false;
  const r = el.getBoundingClientRect();
  const vh = window.innerHeight || document.documentElement.clientHeight;
  if (r.height === 0 && r.width === 0) return false;
  return r.top < vh * frac && r.bottom > 0;
}
function useInView(frac = 0.9) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (seen) return;
    const check = () => { if (isInView(ref.current, frac)) setSeen(true); };
    const un = onScrollCheck(check);
    const ids = [60, 240, 600].map((d) => setTimeout(check, d));
    return () => { un(); ids.forEach(clearTimeout); };
  }, [seen, frac]);
  return [ref, seen];
}

/* ---------- icons ---------- */
function IconChatbot() {
  return (
    <svg viewBox="0 0 24 24" {...ST}>
      <rect x="3" y="5" width="18" height="12" rx="2" />
      <path d="M8 17l-2 3v-3" />
      <circle cx="9" cy="11" r="1" fill="currentColor" stroke="none" />
      <circle cx="15" cy="11" r="1" fill="currentColor" stroke="none" />
      <path d="M12 5V3" />
      <circle cx="12" cy="2.5" r="0.9" fill="currentColor" stroke="none" />
    </svg>
  );
}
function IconAutomation() {
  return (
    <svg viewBox="0 0 24 24" {...ST}>
      <circle cx="12" cy="12" r="3.2" />
      <path d="M12 4.5V7M12 17v2.5M4.5 12H7M17 12h2.5M6.7 6.7l1.8 1.8M15.5 15.5l1.8 1.8M17.3 6.7l-1.8 1.8M8.5 15.5l-1.8 1.8" />
    </svg>
  );
}
function IconVoice() {
  return (
    <svg viewBox="0 0 24 24" {...ST}>
      <rect x="9" y="3" width="6" height="11" rx="3" />
      <path d="M6 11a6 6 0 0 0 12 0" />
      <path d="M12 17v3M9 20h6" />
    </svg>
  );
}
const SERVICE_ICONS = { chatbot: IconChatbot, automation: IconAutomation, voice: IconVoice };

function IconArrow({ size = 16 }) {
  return (<svg width={size} height={size} viewBox="0 0 24 24" {...ST} className="arrow"><path d="M5 12h14M13 6l6 6-6 6" /></svg>);
}
function IconArrowUR({ size = 18 }) {
  return (<svg width={size} height={size} viewBox="0 0 24 24" {...ST} className="sector__arrow"><path d="M7 17L17 7M9 7h8v8" /></svg>);
}
function IconMail() {
  return (<svg width="18" height="18" viewBox="0 0 24 24" {...ST}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3.5 7l8.5 6 8.5-6"/></svg>);
}
function IconPhone() {
  return (<svg width="18" height="18" viewBox="0 0 24 24" {...ST}><path d="M6 3h3l1.5 5-2 1.5a11 11 0 0 0 5 5l1.5-2 5 1.5v3a2 2 0 0 1-2 2A16 16 0 0 1 4 5a2 2 0 0 1 2-2z"/></svg>);
}
function IconCheck() {
  return (<svg width="20" height="20" viewBox="0 0 24 24" {...ST} strokeWidth="2"><path d="M5 12l4.5 4.5L19 7"/></svg>);
}
function IconArrowUp() {
  return (<svg width="14" height="14" viewBox="0 0 24 24" {...ST}><path d="M12 19V5M6 11l6-6 6 6"/></svg>);
}

/* ---------- count-up when scrolled into view ---------- */
function CountUp({ value, duration = 1100 }) {
  const [ref, seen] = useInView(0.92);
  const [n, setN] = useState(value); // final value by default — never stuck at 0
  const done = useRef(false);
  useEffect(() => {
    if (!seen || done.current) return;
    done.current = true;
    const animOk = document.documentElement.classList.contains("anim-ok");
    if (!animOk) { setN(value); return; }   // animations frozen/off → just show it
    setN(0);
    const start = performance.now();
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setN(Math.round(value * eased));
      if (p < 1) requestAnimationFrame(tick);
    };
    requestAnimationFrame(tick);
    const fs = setTimeout(() => setN(value), duration + 500); // failsafe
    return () => clearTimeout(fs);
  }, [seen, value, duration]);
  return <span ref={ref}>{n}</span>;
}

/* ---------- global scroll reveal for [data-reveal] ---------- */
function useScrollReveal() {
  useEffect(() => {
    const check = () => {
      document.querySelectorAll("[data-reveal]:not(.is-in)").forEach((el) => { if (isInView(el, 0.92)) el.classList.add("is-in"); });
    };
    const un = onScrollCheck(check);
    const ids = [40, 200, 500, 1000].map((d) => setTimeout(check, d));
    return () => { un(); ids.forEach(clearTimeout); };
  });
}

Object.assign(window, {
  SERVICE_ICONS, IconChatbot, IconAutomation, IconVoice,
  IconArrow, IconArrowUR, IconMail, IconPhone, IconCheck, IconArrowUp,
  CountUp, useScrollReveal, useInView, isInView, onScrollCheck,
});
