/* Genesis DMA — shared primitives, hooks, icons */
const { useState, useEffect, useRef, useMemo, useCallback, memo } = React;

/* --- Hash router --- */
function useHashRoute() {
  const getPath = () => {
    const h = window.location.hash || '#/';
    return h.replace(/^#/, '') || '/';
  };
  const [path, setPath] = useState(getPath);
  useEffect(() => {
    const onHash = () => {
      setPath(getPath());
      window.scrollTo({ top: 0, behavior: 'auto' });
    };
    window.addEventListener('hashchange', onHash);
    if (!window.location.hash) window.location.hash = '#/';
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  return path;
}

/* --- SEO hook: title, meta description, canonical, og/twitter, JSON-LD --- */
function setMeta(selector, attr, value) {
  let el = document.head.querySelector(selector);
  if (!el) {
    el = document.createElement('meta');
    const [, name] = selector.match(/\[([^=]+)="([^"]+)"\]/) || [];
    // fallback: parse selector crudely
    const m = selector.match(/\[([^=]+)="([^"]+)"\]/);
    if (m) el.setAttribute(m[1], m[2]);
    document.head.appendChild(el);
  }
  el.setAttribute(attr, value);
}
function setLink(rel, href) {
  let el = document.head.querySelector(`link[rel="${rel}"]`);
  if (!el) { el = document.createElement('link'); el.setAttribute('rel', rel); document.head.appendChild(el); }
  el.setAttribute('href', href);
}
function useSEO({ title, description, path, jsonLd, ogImage }) {
  useEffect(() => {
    const canonical = SITE.url + path;
    document.title = title;
    setMeta('meta[name="description"]', 'content', description);
    setLink('canonical', canonical);
    setMeta('meta[property="og:title"]', 'content', title);
    setMeta('meta[property="og:description"]', 'content', description);
    setMeta('meta[property="og:url"]', 'content', canonical);
    setMeta('meta[property="og:image"]', 'content', ogImage || SITE.defaultOg);
    setMeta('meta[name="twitter:title"]', 'content', title);
    setMeta('meta[name="twitter:description"]', 'content', description);
    setMeta('meta[name="twitter:image"]', 'content', ogImage || SITE.defaultOg);

    // Clean up old JSON-LD blocks that we manage
    document.head.querySelectorAll('script[data-gdma-ld]').forEach(n => n.remove());
    const blocks = Array.isArray(jsonLd) ? jsonLd : (jsonLd ? [jsonLd] : []);
    blocks.forEach(obj => {
      const s = document.createElement('script');
      s.type = 'application/ld+json';
      s.setAttribute('data-gdma-ld', '1');
      s.textContent = JSON.stringify(obj);
      document.head.appendChild(s);
    });
  }, [title, description, path, JSON.stringify(jsonLd)]);
}

/* --- Single shared IntersectionObserver for reveals --- */
let sharedRevealObserver = null;
function getRevealObserver() {
  if (sharedRevealObserver) return sharedRevealObserver;
  sharedRevealObserver = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        e.target.classList.add('is-visible');
        sharedRevealObserver.unobserve(e.target);
      }
    });
  }, { rootMargin: '0px 0px -10% 0px', threshold: 0.05 });
  return sharedRevealObserver;
}
function Reveal({ as: Tag = 'div', className = '', children, delay = 0, ...rest }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    if (delay) el.style.transitionDelay = `${delay}ms`;
    getRevealObserver().observe(el);
    return () => getRevealObserver().unobserve(el);
  }, [delay]);
  return <Tag ref={ref} className={`reveal ${className}`} {...rest}>{children}</Tag>;
}

/* --- Icons (1.5px stroke) --- */
const Ico = {
  Arrow:    (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  Plus:     (p) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  Bolt:     (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M13 3 4 14h7l-1 7 9-11h-7l1-7z"/></svg>,
  Search:   (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  Flow:     (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><rect x="3" y="4" width="7" height="6" rx="1"/><rect x="14" y="14" width="7" height="6" rx="1"/><path d="M10 7h4a3 3 0 0 1 3 3v4"/></svg>,
  Chip:     (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><rect x="5" y="5" width="14" height="14" rx="2"/><path d="M9 5V2M15 5V2M9 22v-3M15 22v-3M5 9H2M5 15H2M22 9h-3M22 15h-3"/></svg>,
  Pen:      (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 20h4L20 8l-4-4L4 16v4z"/><path d="M14 6l4 4"/></svg>,
  Chart:    (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><path d="M4 20V8M10 20v-6M16 20v-9M22 20H2"/></svg>,
  Check:    (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m4 12 5 5L20 6"/></svg>,
  Pin:      (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><path d="M12 22s7-6 7-12a7 7 0 1 0-14 0c0 6 7 12 7 12z"/><circle cx="12" cy="10" r="2.5"/></svg>,
  Mail:     (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" {...p}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 7 9-7"/></svg>,
  Phone:    (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M22 16.9v2.5a2 2 0 0 1-2.2 2c-3-.3-5.9-1.4-8.4-3.2a19 19 0 0 1-6-6A19 19 0 0 1 2.2 4.2 2 2 0 0 1 4.2 2h2.5a2 2 0 0 1 2 1.7c.1.9.3 1.8.6 2.7a2 2 0 0 1-.5 2.1L7.5 9.8a16 16 0 0 0 6.7 6.7l1.3-1.3a2 2 0 0 1 2.1-.5c.9.3 1.8.5 2.7.6a2 2 0 0 1 1.7 2z"/></svg>,
};

/* --- Primary / Ghost buttons --- */
function BtnPrimary({ href, children, onClick, ...r }) {
  return <a href={href} onClick={onClick} className="btn-primary" {...r}>{children}<Ico.Arrow /></a>;
}
function BtnGhost({ href, children, onClick, ...r }) {
  return <a href={href} onClick={onClick} className="btn-ghost" {...r}>{children}</a>;
}

/* --- Breadcrumb --- */
function Breadcrumb({ items }) {
  return (
    <nav aria-label="Breadcrumb" className="text-sm text-muted">
      <ol className="flex items-center gap-2 flex-wrap">
        {items.map((it, i) => (
          <li key={i} className="flex items-center gap-2">
            {i > 0 && <span className="text-line2">/</span>}
            {i < items.length - 1
              ? <a href={'#' + it.path} className="link-underline hover:text-white">{it.label}</a>
              : <span className="text-sub" aria-current="page">{it.label}</span>}
          </li>
        ))}
      </ol>
    </nav>
  );
}

/* --- FAQ --- */
function FAQ({ items }) {
  return (
    <section aria-label="Frequently asked questions">
      {items.map(([q, a], i) => (
        <details key={i} className="faq">
          <summary>
            <span>{q}</span>
            <span className="ico"><Ico.Plus /></span>
          </summary>
          <div className="faq-body"><p>{a}</p></div>
        </details>
      ))}
    </section>
  );
}

/* --- Section wrapper --- */
function Section({ id, label, title, intro, children, className = '' }) {
  return (
    <section id={id} className={`container-x py-12 md:py-20 ${className}`}>
      {(label || title || intro) && (
        <div className="mb-10 md:mb-12 max-w-3xl">
          {label && <Reveal className="text-teal text-xs tracking-[0.2em] uppercase mb-4">{label}</Reveal>}
          {title && <Reveal as="h2" className="font-semibold text-white" style={{ fontSize: 'clamp(2.25rem, 5vw, 4rem)', lineHeight: 1.05, letterSpacing: '-0.02em' }}>{title}</Reveal>}
          {intro && <Reveal className="text-sub mt-6 text-lg max-w-2xl">{intro}</Reveal>}
        </div>
      )}
      {children}
    </section>
  );
}

/* --- Counter (count-up on intersect) --- */
function Counter({ to, prefix = '', suffix = '', duration = 1500 }) {
  const ref = useRef(null);
  const [val, setVal] = useState(0);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting) {
        const start = performance.now();
        const step = (t) => {
          const p = Math.min(1, (t - start) / duration);
          const eased = 1 - Math.pow(1 - p, 3);
          setVal(Math.round(to * eased));
          if (p < 1) requestAnimationFrame(step);
        };
        requestAnimationFrame(step);
        io.disconnect();
      }
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  return <span ref={ref}>{prefix}{val.toLocaleString()}{suffix}</span>;
}

Object.assign(window, {
  useHashRoute, useSEO, Reveal, Ico, BtnPrimary, BtnGhost, Breadcrumb, FAQ, Section, Counter,
});
