/* Feedback ORG — shared lib: hooks, bus, icon + placeholder helpers */
const { useState, useEffect, useRef, useCallback } = React;

/* ---------- event bus: any CTA opens the shared modals ---------- */
const fbBus = {
  open(name, payload) { document.dispatchEvent(new CustomEvent('fb:open', { detail: { name, payload } })); },
};

/* ---------- lucide helper ---------- */
function refreshIcons() { if (window.lucide) window.lucide.createIcons(); }
function Icon({ name, size = 24, style = {}, strokeWidth = 1.6 }) {
  return <i data-lucide={name} style={{ width: size, height: size, display: 'inline-flex', ...style }} data-stroke={strokeWidth}></i>;
}

/* ---------- in-view (rect + scroll; robust across sandboxed iframes) ---------- */
function useInView(opts = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setInView(true); return; }
    let done = false;
    const trigger = opts.trigger ?? 0.9; // fire when top is within 90% of viewport
    const check = () => {
      if (done) return;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (r.top < vh * trigger && r.bottom > 0) { done = true; setInView(true); cleanup(); }
    };
    const cleanup = () => {
      window.removeEventListener('scroll', check);
      window.removeEventListener('resize', check);
    };
    window.addEventListener('scroll', check, { passive: true });
    window.addEventListener('resize', check);
    const raf = requestAnimationFrame(check);
    const t = setTimeout(check, 140);
    return () => { cleanup(); cancelAnimationFrame(raf); clearTimeout(t); };
  }, []);
  return [ref, inView];
}

/* ---------- reveal wrapper (adds .is-in + stagger delay; self-settles) ---------- */
function Reveal({ children, delay = 0, style = {}, className = '', as = 'div', ...rest }) {
  const [ref, inView] = useInView();
  const [settled, setSettled] = useState(false);
  useEffect(() => {
    if (!inView) return;
    const t = setTimeout(() => setSettled(true), 760 + delay);
    return () => clearTimeout(t);
  }, [inView]);
  const Tag = as;
  return (
    <Tag ref={ref} className={`reveal ${inView ? 'is-in' : ''} ${settled ? 'is-settled' : ''} ${className}`}
      style={{ transitionDelay: `${delay}ms`, ...style }} {...rest}>
      {children}
    </Tag>
  );
}

/* ---------- count-up (fires once when in view) ---------- */
function useCountUp(end, inView, dur = 1100) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!inView) return;
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setVal(end); 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);
      setVal(end * eased);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    // failsafe: if rAF is throttled (background/sandboxed tab), guarantee final value
    const settle = setTimeout(() => setVal(end), dur + 400);
    return () => { cancelAnimationFrame(raf); clearTimeout(settle); };
  }, [inView, end]);
  return val;
}

/* ---------- eyebrow label ---------- */
function Eyebrow({ children, style = {} }) {
  return <div className="fb-eyebrow" style={{ display: 'inline-flex', alignItems: 'center', gap: 8, ...style }}>{children}</div>;
}

/* ---------- icon tile (outline mono, lights lime on card hover) ---------- */
function IconTile({ name, size = 52, icon = 28, lit = false }) {
  return (
    <div className={`icon-tile ${lit ? 'lit' : ''}`} style={{
      width: size, height: size, flexShrink: 0,
      borderRadius: 'var(--radius)',
      background: 'var(--fb-ink)',
      border: '1px solid var(--border-strong)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <Icon name={name} size={icon} />
    </div>
  );
}

/* ---------- reserved-image placeholder (neutral, never stock) ---------- */
function ImageReserve({ label = 'Imagem reservada', icon = 'image', ratio, height, style = {}, children, dashed = true }) {
  return (
    <div style={{
      position: 'relative',
      width: '100%',
      aspectRatio: ratio || undefined,
      height: height || undefined,
      borderRadius: 'var(--radius-lg)',
      background: 'linear-gradient(180deg, #232228 0%, #1c1b20 100%)',
      border: `1px ${dashed ? 'dashed' : 'solid'} var(--border-strong)`,
      overflow: 'hidden',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      ...style,
    }}>
      {/* faint contour motif */}
      <div aria-hidden style={{ position: 'absolute', inset: 0, opacity: 0.5, pointerEvents: 'none',
        backgroundImage: 'radial-gradient(circle at 78% 18%, rgba(206,216,72,0.05), transparent 42%)' }}></div>
      {children || (
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12, color: 'var(--text-dim)' }}>
          <div style={{ width: 46, height: 46, borderRadius: '50%', border: '1px solid var(--border-strong)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-muted)' }}>
            <Icon name={icon} size={22} />
          </div>
          <span style={{ fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 600, color: 'var(--text-muted)' }}>{label}</span>
        </div>
      )}
    </div>
  );
}

/* ---------- section shell ---------- */
function Section({ id, children, style = {}, bleed = false, padY }) {
  return (
    <section id={id} data-screen-label={id} style={{
      padding: padY || 'clamp(64px, 9vw, 120px) clamp(20px, 5vw, 72px)',
      ...style,
    }}>
      <div style={{ maxWidth: bleed ? '100%' : 1200, margin: '0 auto' }}>{children}</div>
    </section>
  );
}

Object.assign(window, {
  fbBus, refreshIcons, Icon, useInView, Reveal, useCountUp,
  Eyebrow, IconTile, ImageReserve, Section,
});
