/* global React */
// ============================================================
// Craque Cidadão — shared utilities (Icon, motion, decorations)
// ============================================================

const CC_LOGO = 'assets/logo-craque-vertical-onwhite.png';

// WhatsApp config (used by floating button + CTAs)
const WA_NUMBER = '5521966377153';
const WA_MSG = encodeURIComponent('Olá! Vim pelo site da ONG Craque Cidadão e gostaria de saber mais.');
const WA_LINK = `https://wa.me/${WA_NUMBER}?text=${WA_MSG}`;
const IG_LINK = 'https://www.instagram.com/ongcraquecidadao/';

// Lucide icon helper — injects a detached <i data-lucide> that lucide swaps,
// so React never owns the replaced node (no reconciliation errors).
function Icon({ name, size = 20, color = 'currentColor', strokeWidth = 2, style = {} }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const host = ref.current;
    if (!host || !window.lucide) return;
    host.innerHTML = '';
    const tmp = document.createElement('i');
    tmp.setAttribute('data-lucide', name);
    tmp.setAttribute('width', size);
    tmp.setAttribute('height', size);
    tmp.setAttribute('stroke-width', strokeWidth);
    host.appendChild(tmp);
    window.lucide.createIcons();
  }, [name, size, strokeWidth]);
  return <span ref={ref} style={{ display: 'inline-flex', width: size, height: size, color, ...style }} />;
}

// Global motion preference (set by Tweaks; defaults to subtle)
window.CC_MOTION = window.CC_MOTION || 'subtle';

// Reveal — fade/slide a block in when it scrolls into view.
function Reveal({ children, delay = 0, y = 24, as = 'div', style = {}, ...rest }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(window.CC_MOTION === 'off');
  React.useEffect(() => {
    if (window.CC_MOTION === 'off') { setShown(true); return; }
    const el = ref.current;
    if (!el) return;
    // Already in view on mount? show immediately.
    const r = el.getBoundingClientRect();
    if (r.top < (window.innerHeight || 800) && r.bottom > 0) setShown(true);
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    io.observe(el);
    // Failsafe: if IO never delivers (some embedded previews), reveal anyway.
    const fs = setTimeout(() => setShown(true), 700);
    return () => { io.disconnect(); clearTimeout(fs); };
  }, []);
  const Tag = as;
  return (
    <Tag ref={ref} style={{
      opacity: shown ? 1 : 0,
      transform: shown ? 'none' : `translateY(${y}px)`,
      transition: `opacity 620ms var(--ease-out) ${delay}ms, transform 620ms var(--ease-out) ${delay}ms`,
      ...style,
    }} {...rest}>{children}</Tag>
  );
}

// CountUp — animated numeral. Counts when scrolled into view.
function CountUp({ end, duration = 1400, prefix = '+', className, style }) {
  const ref = React.useRef(null);
  const [val, setVal] = React.useState(window.CC_MOTION === 'off' ? end : 0);
  React.useEffect(() => {
    if (window.CC_MOTION === 'off') { setVal(end); return; }
    const el = ref.current;
    if (!el) return;
    let raf, started = false;
    const run = (ts0) => {
      const step = (ts) => {
        const p = Math.min(1, (ts - ts0) / duration);
        const eased = 1 - Math.pow(1 - p, 3);
        setVal(Math.round(eased * end));
        if (p < 1) raf = requestAnimationFrame(step);
      };
      raf = requestAnimationFrame(step);
    };
    const start = () => { if (!started) { started = true; requestAnimationFrame(run); io.disconnect(); } };
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) start(); });
    }, { threshold: 0.4 });
    io.observe(el);
    // If already on screen at mount, kick it off.
    const r = el.getBoundingClientRect();
    if (r.top < (window.innerHeight || 800) && r.bottom > 0) start();
    // Failsafe: if IO never delivers, snap to the final value.
    const fs = setTimeout(() => { if (!started) { started = true; setVal(end); } }, 800);
    return () => { io.disconnect(); clearTimeout(fs); if (raf) cancelAnimationFrame(raf); };
  }, [end]);
  const padded = String(val).padStart(String(end).length >= 2 && end < 100 ? 2 : 0, '0');
  return (
    <span ref={ref} className={className} style={style}>
      <span style={{ fontSize: '0.55em', fontWeight: 800, verticalAlign: '0.18em', marginRight: 1 }}>{prefix}</span>
      {padded}
    </span>
  );
}

// CourtLines — subtle futsal-court decoration for dark/blue areas.
function CourtLines({ opacity = 0.12, color = '#fff' }) {
  return (
    <svg aria-hidden viewBox="0 0 1200 600" preserveAspectRatio="xMidYMid slice" style={{
      position: 'absolute', inset: 0, width: '100%', height: '100%', opacity, pointerEvents: 'none',
    }}>
      <g fill="none" stroke={color} strokeWidth="2">
        <line x1="600" y1="0" x2="600" y2="600" />
        <circle cx="600" cy="300" r="92" />
        <circle cx="600" cy="300" r="6" fill={color} stroke="none" />
        <rect x="0" y="170" width="150" height="260" />
        <rect x="0" y="240" width="64" height="120" />
        <rect x="1050" y="170" width="150" height="260" />
        <rect x="1136" y="240" width="64" height="120" />
        <path d="M150 220 A 90 90 0 0 1 150 380" />
        <path d="M1050 220 A 90 90 0 0 0 1050 380" />
      </g>
    </svg>
  );
}

// Speed lines — energetic diagonal motion streaks (decorative).
function SpeedLines({ color = 'var(--gold-400)', style = {} }) {
  return (
    <svg aria-hidden viewBox="0 0 120 80" style={{ display: 'block', ...style }}>
      <g stroke={color} strokeWidth="6" strokeLinecap="round">
        <line x1="6" y1="20" x2="70" y2="20" opacity="0.9" />
        <line x1="20" y1="40" x2="100" y2="40" opacity="0.7" />
        <line x1="40" y1="60" x2="114" y2="60" opacity="0.5" />
      </g>
    </svg>
  );
}

// Section wrapper with consistent vertical rhythm (density-aware via --cc-sy).
function Section({ children, bg = 'transparent', style = {}, narrow = false, id }) {
  return (
    <section id={id} style={{ background: bg, ...style }}>
      <div style={{
        maxWidth: narrow ? 'var(--container-narrow)' : 'var(--container)',
        margin: '0 auto', padding: 'var(--cc-sy, 88px) 24px',
      }}>{children}</div>
    </section>
  );
}

// Official WhatsApp glyph.
function WAIcon({ size = 20, color = 'currentColor' }) {
  return (
    <svg viewBox="0 0 24 24" width={size} height={size} fill={color} aria-hidden style={{ display: 'block' }}>
      <path d="M.057 24l1.687-6.163a11.867 11.867 0 01-1.587-5.946C.16 5.335 5.495 0 12.05 0a11.817 11.817 0 018.413 3.488 11.824 11.824 0 013.48 8.414c-.003 6.557-5.338 11.892-11.893 11.892a11.9 11.9 0 01-5.688-1.448L.057 24zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884a9.86 9.86 0 001.51 5.26l-.999 3.648 3.728-.978zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414z" />
    </svg>
  );
}

// Polished WhatsApp button — official glyph, gradient, hover lift. Shared everywhere.
function WAButton({ children = 'Fale pelo WhatsApp', size = 'lg', full = false, style = {} }) {
  const [h, setH] = React.useState(false);
  const S = {
    sm: { padding: '9px 16px', fs: 13.5, ic: 16, gap: 8 },
    md: { padding: '12px 20px', fs: 15, ic: 18, gap: 9 },
    lg: { padding: '15px 28px', fs: 16.5, ic: 21, gap: 11 },
  }[size];
  return (
    <a href={WA_LINK} target="_blank" rel="noopener"
      onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        display: full ? 'flex' : 'inline-flex', width: full ? '100%' : undefined,
        alignItems: 'center', justifyContent: 'center', gap: S.gap,
        padding: S.padding, borderRadius: 'var(--radius-pill)', textDecoration: 'none',
        fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: S.fs, letterSpacing: '0.01em',
        color: '#fff', background: 'linear-gradient(135deg, #2BD96E 0%, #1EBE5B 100%)',
        boxShadow: h ? '0 16px 34px rgba(30,190,91,0.45)' : '0 10px 24px rgba(30,190,91,0.32)',
        transform: h ? 'translateY(-2px)' : 'none',
        transition: 'transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out)',
        whiteSpace: 'nowrap',
      }}>
      <WAIcon size={S.ic} color="#fff" /> {children}
    </a>
  );
}

Object.assign(window, { CC_LOGO, WA_NUMBER, WA_LINK, IG_LINK, Icon, WAIcon, WAButton, Reveal, CountUp, CourtLines, SpeedLines, Section });
