/* Motion primitives & microinteractions */

const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* ── SCROLL REVEAL ──────────────────────────────────────────────────── */
const Reveal = ({ children, delay = 0, y = 24, x = 0, dur = 600, once = true, scale = 1, style }) => {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setVisible(true);
        if (once) obs.disconnect();
      } else if (!once) setVisible(false);
    }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, [once]);
  return (
    <div ref={ref} style={{
      transform: visible ? 'none' : `translate(${x}px, ${y}px) scale(${scale === 1 ? 1 : visible ? 1 : scale})`,
      opacity: visible ? 1 : 0,
      transition: `transform ${dur}ms cubic-bezier(.2,.7,.3,1) ${delay}ms, opacity ${dur}ms ease ${delay}ms`,
      willChange: 'transform, opacity',
      ...style,
    }}>{children}</div>
  );
};

/* Stagger children */
const Stagger = ({ children, baseDelay = 0, step = 80, ...props }) => (
  <>
    {React.Children.map(children, (c, i) => (
      <Reveal key={i} delay={baseDelay + i * step} {...props}>{c}</Reveal>
    ))}
  </>
);

/* ── COUNT UP ───────────────────────────────────────────────────────── */
const CountUp = ({ to, from = 0, dur = 1400, prefix = '', suffix = '', sep = ',', decimals = 0, style }) => {
  const ref = useRef(null);
  const [value, setValue] = useState(from);
  const started = useRef(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting && !started.current) {
        started.current = true;
        const t0 = performance.now();
        const animate = (t) => {
          const p = Math.min(1, (t - t0) / dur);
          const eased = 1 - Math.pow(1 - p, 3);
          setValue(from + (to - from) * eased);
          if (p < 1) requestAnimationFrame(animate);
        };
        requestAnimationFrame(animate);
      }
    }, { threshold: 0.4 });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, [to, from, dur]);
  const fmt = (n) => {
    const fixed = decimals > 0 ? n.toFixed(decimals) : Math.round(n).toString();
    const [intPart, decPart] = fixed.split('.');
    const withSep = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, sep);
    return decPart ? `${withSep}.${decPart}` : withSep;
  };
  return <span ref={ref} style={style}>{prefix}{fmt(value)}{suffix}</span>;
};

/* ── TILT ───────────────────────────────────────────────────────────── */
const Tilt = ({ children, max = 8, scale = 1.02, glare = false, style }) => {
  const ref = useRef(null);
  const onMove = (e) => {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    const cx = (e.clientX - r.left) / r.width - 0.5;
    const cy = (e.clientY - r.top) / r.height - 0.5;
    el.style.transform = `perspective(1000px) rotateY(${cx * max}deg) rotateX(${-cy * max}deg) scale(${scale})`;
    if (glare) {
      const glareEl = el.querySelector('.tilt-glare');
      if (glareEl) {
        glareEl.style.background = `linear-gradient(${135 + cx * 90}deg, rgba(255,255,255,${0.15 + Math.abs(cx) * 0.2}), transparent 60%)`;
      }
    }
  };
  const onLeave = () => {
    if (!ref.current) return;
    ref.current.style.transform = '';
  };
  return (
    <div ref={ref} onMouseMove={onMove} onMouseLeave={onLeave}
      style={{ transition: 'transform .25s cubic-bezier(.2,.7,.3,1)', transformStyle: 'preserve-3d', position: 'relative', ...style }}>
      {children}
      {glare && <div className="tilt-glare" style={{ position: 'absolute', inset: 0, pointerEvents: 'none', borderRadius: 'inherit' }} />}
    </div>
  );
};

/* ── MAGNETIC BUTTON ────────────────────────────────────────────────── */
const Magnetic = ({ children, strength = 0.3, style }) => {
  const ref = useRef(null);
  const onMove = (e) => {
    const r = ref.current.getBoundingClientRect();
    const dx = (e.clientX - (r.left + r.width / 2)) * strength;
    const dy = (e.clientY - (r.top + r.height / 2)) * strength;
    ref.current.style.transform = `translate(${dx}px, ${dy}px)`;
  };
  const onLeave = () => { if (ref.current) ref.current.style.transform = ''; };
  return (
    <span ref={ref} onMouseMove={onMove} onMouseLeave={onLeave}
      style={{ display: 'inline-block', transition: 'transform .35s cubic-bezier(.2,.9,.3,1.2)', ...style }}>
      {children}
    </span>
  );
};

/* ── RIPPLE on click ────────────────────────────────────────────────── */
const useRipple = () => {
  return useCallback((e) => {
    const btn = e.currentTarget;
    const rect = btn.getBoundingClientRect();
    const r = document.createElement('span');
    const size = Math.max(rect.width, rect.height);
    r.style.cssText = `
      position:absolute;width:${size}px;height:${size}px;border-radius:50%;
      left:${e.clientX - rect.left - size / 2}px;top:${e.clientY - rect.top - size / 2}px;
      background:rgba(255,255,255,0.4);pointer-events:none;transform:scale(0);
      animation:ripple .6s ease-out;
    `;
    if (getComputedStyle(btn).position === 'static') btn.style.position = 'relative';
    btn.style.overflow = 'hidden';
    btn.appendChild(r);
    setTimeout(() => r.remove(), 600);
  }, []);
};

/* ── CONFETTI ───────────────────────────────────────────────────────── */
const Confetti = ({ trigger, colors }) => {
  const [pieces, setPieces] = useState([]);
  useEffect(() => {
    if (!trigger) return;
    const cs = colors || ['#1e90ff', '#22d3ee', '#22c55e', '#f59e0b', '#a855f7', '#ef4444'];
    const list = Array.from({ length: 60 }, (_, i) => ({
      id: Date.now() + i,
      left: 40 + Math.random() * 20,
      vx: (Math.random() - 0.5) * 200,
      vy: -150 - Math.random() * 200,
      color: cs[i % cs.length],
      size: 6 + Math.random() * 6,
      rot: Math.random() * 360,
      delay: Math.random() * 100,
    }));
    setPieces(list);
    const t = setTimeout(() => setPieces([]), 2400);
    return () => clearTimeout(t);
  }, [trigger]);
  if (!pieces.length) return null;
  return (
    <div style={{ position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 2000, overflow: 'hidden' }}>
      {pieces.map(p => (
        <div key={p.id} style={{
          position: 'absolute', left: `${p.left}%`, top: '50%',
          width: p.size, height: p.size * 0.4, background: p.color,
          borderRadius: 2,
          transform: `rotate(${p.rot}deg)`,
          animation: `confetti 2.2s ${p.delay}ms cubic-bezier(.2,.7,.3,1) forwards`,
          '--vx': `${p.vx}px`, '--vy': `${p.vy}px`,
        }} />
      ))}
    </div>
  );
};

/* ── TOAST ──────────────────────────────────────────────────────────── */
const ToastCtx = React.createContext({ push: () => {} });
const ToastProvider = ({ children }) => {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((toast) => {
    const id = Date.now() + Math.random();
    setToasts(t => [...t, { id, ...toast }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), toast.duration || 3500);
  }, []);
  return (
    <ToastCtx.Provider value={{ push }}>
      {children}
      <div style={{
        position: 'fixed', top: 20, right: 20, zIndex: 3000,
        display: 'grid', gap: 8,
      }}>
        {toasts.map(t => <ToastItem key={t.id} {...t} />)}
      </div>
    </ToastCtx.Provider>
  );
};
const ToastItem = ({ kind = 'info', title, body, theme }) => {
  const colors = { info: '#3b82f6', success: '#22c55e', warning: '#f59e0b', danger: '#ef4444', wa: '#25d366' };
  const icons = { info: 'info', success: 'check', warning: 'warning', danger: 'warning', wa: 'wa' };
  const c = colors[kind];
  return (
    <div style={{
      minWidth: 320, maxWidth: 380, padding: 14, borderRadius: 12,
      background: (theme && theme.bgElev) || '#fff',
      border: `1px solid ${(theme && theme.borderStrong) || 'rgba(0,0,0,0.1)'}`,
      boxShadow: `0 12px 40px rgba(0,0,0,0.18), 0 0 0 1px ${c}33`,
      display: 'flex', gap: 12, alignItems: 'flex-start',
      animation: 'toastIn .35s cubic-bezier(.2,.9,.3,1.2)',
      fontFamily: 'Inter, sans-serif',
    }}>
      <div style={{
        width: 36, height: 36, borderRadius: 10, background: `${c}22`, color: c,
        display: 'grid', placeItems: 'center', flexShrink: 0,
      }}><Icon name={icons[kind] || 'info'} size={18} /></div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 700, color: (theme && theme.text) || '#111', marginBottom: 2 }}>{title}</div>
        {body && <div style={{ fontSize: 12, color: (theme && theme.textDim) || '#666', lineHeight: 1.4 }}>{body}</div>}
      </div>
    </div>
  );
};
const useToast = () => React.useContext(ToastCtx);

/* ── SKELETON ───────────────────────────────────────────────────────── */
const Skeleton = ({ w = '100%', h = 14, r = 6, style }) => (
  <div style={{
    width: w, height: h, borderRadius: r,
    background: 'linear-gradient(90deg, rgba(128,128,128,0.08) 25%, rgba(128,128,128,0.18) 50%, rgba(128,128,128,0.08) 75%)',
    backgroundSize: '200% 100%',
    animation: 'shimmer 1.6s linear infinite',
    ...style,
  }} />
);

/* ── PULSE DOT (live indicator) ─────────────────────────────────────── */
const PulseDot = ({ color = '#22c55e', size = 8 }) => (
  <span style={{ position: 'relative', display: 'inline-block', width: size, height: size }}>
    <span style={{
      position: 'absolute', inset: 0, borderRadius: '50%', background: color,
      animation: 'pulseRing 1.8s ease-out infinite',
    }} />
    <span style={{
      position: 'absolute', inset: 0, borderRadius: '50%', background: color,
      boxShadow: `0 0 8px ${color}`,
    }} />
  </span>
);

/* ── ANIMATED WHATSAPP SEND ─────────────────────────────────────────── */
const SendAnimation = ({ trigger, color = '#25d366' }) => {
  const [active, setActive] = useState(false);
  useEffect(() => {
    if (trigger) {
      setActive(true);
      const t = setTimeout(() => setActive(false), 1200);
      return () => clearTimeout(t);
    }
  }, [trigger]);
  if (!active) return null;
  return (
    <div style={{
      position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 2500,
      display: 'grid', placeItems: 'center',
    }}>
      <div style={{
        width: 80, height: 80, borderRadius: '50%', background: color, color: '#fff',
        display: 'grid', placeItems: 'center',
        animation: 'sendFly 1.1s cubic-bezier(.2,.7,.3,1) forwards',
        boxShadow: `0 12px 60px ${color}66`,
      }}>
        <Icon name="send" size={36} />
      </div>
    </div>
  );
};

/* ── TYPING DOTS ────────────────────────────────────────────────────── */
const TypingDots = ({ color = 'currentColor' }) => (
  <span style={{ display: 'inline-flex', gap: 4, alignItems: 'center' }}>
    {[0, 1, 2].map(i => (
      <span key={i} style={{
        width: 5, height: 5, borderRadius: '50%', background: color,
        animation: `typingBob 1.2s ease-in-out ${i * 0.15}s infinite`,
      }} />
    ))}
  </span>
);

/* ── PROGRESS BAR (animated) ────────────────────────────────────────── */
const ProgressBar = ({ value, max = 100, color, bg, height = 8, animated = true }) => {
  const pct = Math.min(100, (value / max) * 100);
  return (
    <div style={{
      width: '100%', height, borderRadius: height / 2,
      background: bg || 'rgba(128,128,128,0.15)', overflow: 'hidden',
    }}>
      <div style={{
        height: '100%', width: `${pct}%`,
        background: color || 'linear-gradient(90deg, #1e90ff, #22d3ee)',
        borderRadius: height / 2,
        transition: animated ? 'width 1.4s cubic-bezier(.2,.7,.3,1)' : 'none',
        position: 'relative', overflow: 'hidden',
      }}>
        {animated && (
          <div style={{
            position: 'absolute', inset: 0,
            background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.35), transparent)',
            animation: 'shimmer 2s linear infinite',
          }} />
        )}
      </div>
    </div>
  );
};

/* Inject keyframes for these animations into <style> */
if (typeof document !== 'undefined' && !document.getElementById('motion-styles')) {
  const s = document.createElement('style');
  s.id = 'motion-styles';
  s.textContent = `
    @keyframes ripple { to { transform: scale(2.5); opacity: 0; } }
    @keyframes confetti {
      to { transform: translate(var(--vx), calc(100vh + var(--vy))) rotate(720deg); opacity: 0; }
    }
    @keyframes toastIn {
      from { opacity: 0; transform: translateX(40px) scale(0.95); }
      to { opacity: 1; transform: translateX(0) scale(1); }
    }
    @keyframes pulseRing {
      0% { transform: scale(1); opacity: 0.7; }
      100% { transform: scale(2.8); opacity: 0; }
    }
    @keyframes sendFly {
      0% { transform: translate(0,0) scale(0); opacity: 0; }
      30% { transform: translate(0,0) scale(1); opacity: 1; }
      100% { transform: translate(40vw, -50vh) scale(0.4) rotate(45deg); opacity: 0; }
    }
    @keyframes typingBob {
      0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
      30% { transform: translateY(-4px); opacity: 1; }
    }
    @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
    @keyframes bounceIn {
      0% { transform: scale(0.3); opacity: 0; }
      50% { transform: scale(1.1); opacity: 1; }
      70% { transform: scale(0.95); }
      100% { transform: scale(1); }
    }
    @keyframes slideInRight {
      from { opacity: 0; transform: translateX(40px); }
      to { opacity: 1; transform: translateX(0); }
    }
    @keyframes glow {
      0%, 100% { box-shadow: 0 0 20px var(--glow-color, rgba(30,144,255,0.4)); }
      50% { box-shadow: 0 0 40px var(--glow-color, rgba(30,144,255,0.7)); }
    }
    @keyframes rotateBall {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
    @keyframes scrollIndicator {
      0% { transform: translateY(0); opacity: 0.6; }
      50% { transform: translateY(8px); opacity: 1; }
      100% { transform: translateY(0); opacity: 0.6; }
    }
    .hover-lift { transition: transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s; }
    .hover-lift:hover { transform: translateY(-4px); }
    .hover-scale { transition: transform .25s cubic-bezier(.2,.7,.3,1); }
    .hover-scale:hover { transform: scale(1.04); }
  `;
  document.head.appendChild(s);
}

Object.assign(window, {
  Reveal, Stagger, CountUp, Tilt, Magnetic, useRipple,
  Confetti, ToastProvider, useToast, Skeleton, PulseDot,
  SendAnimation, TypingDots, ProgressBar,
});
