/* Shared lib: hooks, small components, icons. All exported to window. */

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

// ——— Reveal on scroll ———
function useInView(options = { threshold: 0.15, rootMargin: '-40px 0px' }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setInView(true); obs.disconnect(); }
    }, options);
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

function Reveal({ children, delay = 0, className = '', as: Tag = 'div', ...rest }) {
  const [ref, inView] = useInView();
  const cls = `reveal ${inView ? 'in' : ''} ${delay ? `reveal-delay-${delay}` : ''} ${className}`;
  return <Tag ref={ref} className={cls} {...rest}>{children}</Tag>;
}

// ——— Scroll progress (0 to 1) scoped to a ref ———
function useScrollProgress(ref) {
  const [p, setP] = useState(0);
  useEffect(() => {
    const handler = () => {
      if (!ref.current) return;
      const r = ref.current.getBoundingClientRect();
      const vh = window.innerHeight;
      const total = r.height + vh;
      const passed = vh - r.top;
      const prog = Math.max(0, Math.min(1, passed / total));
      setP(prog);
    };
    handler();
    window.addEventListener('scroll', handler, { passive: true });
    window.addEventListener('resize', handler);
    return () => {
      window.removeEventListener('scroll', handler);
      window.removeEventListener('resize', handler);
    };
  }, [ref]);
  return p;
}

// ——— Count up ———
function CountUp({ to, duration = 1600, prefix = '', suffix = '', decimals = 0, format = null }) {
  const [ref, inView] = useInView();
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!inView) return;
    let raf, start;
    const step = (t) => {
      if (!start) start = t;
      const p = Math.min(1, (t - start) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setVal(to * eased);
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [inView, to, duration]);
  const display = format ? format(val) : `${prefix}${val.toFixed(decimals)}${suffix}`;
  return <span ref={ref}>{display}</span>;
}

// ——— Magnetic button ———
function useMagnetic(_strength) {
  return useRef(null);
}

function MagneticBtn({ children, className = '', onClick, variant = 'primary', href, ...rest }) {
  const ref = useMagnetic(0.2);
  const Tag = href ? 'a' : 'button';
  return (
    <Tag ref={ref} href={href} className={`btn btn-${variant} ${className}`} onClick={onClick} data-cursor="hover" style={href ? { textDecoration: 'none' } : undefined} {...rest}>
      {children}
    </Tag>
  );
}

// ——— Fade+blur text entry ———
function SplitText({ text, className = '', delay = 0 }) {
  const [ref, inView] = useInView();
  return (
    <span ref={ref} className={className} style={{
      display: 'inline-block',
      opacity: inView ? 1 : 0,
      filter: inView ? 'blur(0px)' : 'blur(14px)',
      transform: inView ? 'translateY(0)' : 'translateY(12px)',
      transition: `opacity 1.1s cubic-bezier(.2,.7,.2,1) ${delay}s, filter 1.1s cubic-bezier(.2,.7,.2,1) ${delay}s, transform 1.1s cubic-bezier(.2,.7,.2,1) ${delay}s`,
    }}>{text}</span>
  );
}

// ——— Blur-in reveal with direction support ———
// direction: 'up' | 'down' | 'left' | 'right' | 'none'
function BlurIn({ children, delay = 0, direction = 'up', distance = 14, blur = 12, duration = 1, className = '', style = {}, as: Tag = 'div' }) {
  const [ref, inView] = useInView({ threshold: 0.08, rootMargin: '-20px 0px' });
  const deltaMap = {
    up:    `translateY(${distance}px)`,
    down:  `translateY(-${distance}px)`,
    left:  `translateX(${distance}px)`,
    right: `translateX(-${distance}px)`,
    none:  'none',
  };
  const base = {
    opacity: inView ? 1 : 0,
    filter: inView ? 'blur(0px)' : `blur(${blur}px)`,
    transform: inView ? 'none' : deltaMap[direction] || deltaMap.up,
    transition: `opacity ${duration}s cubic-bezier(.2,.7,.2,1) ${delay}s, filter ${duration}s cubic-bezier(.2,.7,.2,1) ${delay}s, transform ${duration}s cubic-bezier(.2,.7,.2,1) ${delay}s`,
    willChange: 'opacity, transform, filter',
  };
  return <Tag ref={ref} className={className} style={{ ...base, ...style }}>{children}</Tag>;
}

// ——— Icons (inline SVG) ———
const Icon = {
  Arrow: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M3 11L11 3M11 3H5M11 3V9" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
  ),
  ArrowDown: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M7 3V11M7 11L3 7M7 11L11 7" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
  ),
  Check: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M2.5 7.5L5.5 10.5L11.5 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>
  ),
  Close: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M3 3L11 11M3 11L11 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
  ),
  Menu: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M2 3.5H12M2 7H12M2 10.5H12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
  ),
  Plus: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M7 3V11M3 7H11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
  ),
  Minus: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M3 7H11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
  ),
  Sun: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="2.5" stroke="currentColor" strokeWidth="1.3"/><path d="M7 1V2.5M7 11.5V13M13 7H11.5M2.5 7H1M11.24 2.76L10.18 3.82M3.82 10.18L2.76 11.24M11.24 11.24L10.18 10.18M3.82 3.82L2.76 2.76" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/></svg>
  ),
  Moon: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M11.5 8.5A5 5 0 115.5 2.5 4 4 0 0011.5 8.5Z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
  ),
  Spark: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M7 1L8.5 5.5L13 7L8.5 8.5L7 13L5.5 8.5L1 7L5.5 5.5L7 1Z" fill="currentColor"/></svg>
  ),
  Bolt: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><path d="M7.5 1L2 8H7L6.5 13L12 6H7L7.5 1Z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>
  ),
  Play: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="currentColor"><path d="M4 2.5L11 7L4 11.5V2.5Z"/></svg>
  ),
  Pause: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="currentColor"><rect x="3.5" y="2.5" width="2.5" height="9" rx="0.5"/><rect x="8" y="2.5" width="2.5" height="9" rx="0.5"/></svg>
  ),
  Book: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><path d="M3 3h4a3 3 0 013 3v7a2 2 0 00-2-2H3V3z" stroke="currentColor" strokeWidth="1.3"/><path d="M13 3H9a3 3 0 00-3 3v7a2 2 0 012-2h5V3z" stroke="currentColor" strokeWidth="1.3"/></svg>
  ),
  Layers: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><path d="M8 2L2 5l6 3 6-3-6-3z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/><path d="M2 8l6 3 6-3M2 11l6 3 6-3" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
  ),
  Chart: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><path d="M2 13V3M2 13h12" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/><path d="M5 11V8M8 11V5M11 11V7" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
  ),
  Chat: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><path d="M3 3h10a1 1 0 011 1v7a1 1 0 01-1 1H6l-3 2V3z" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round"/></svg>
  ),
  Grid: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><rect x="2" y="2" width="5" height="5" stroke="currentColor" strokeWidth="1.3"/><rect x="9" y="2" width="5" height="5" stroke="currentColor" strokeWidth="1.3"/><rect x="2" y="9" width="5" height="5" stroke="currentColor" strokeWidth="1.3"/><rect x="9" y="9" width="5" height="5" stroke="currentColor" strokeWidth="1.3"/></svg>
  ),
  Flow: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><circle cx="4" cy="4" r="2" stroke="currentColor" strokeWidth="1.3"/><circle cx="12" cy="12" r="2" stroke="currentColor" strokeWidth="1.3"/><path d="M6 4h4a2 2 0 012 2v4" stroke="currentColor" strokeWidth="1.3"/></svg>
  ),
  Trend: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><path d="M2 11L6 7L9 10L14 4M14 4H10M14 4V8" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
  ),
  Calendar: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="11" rx="1" stroke="currentColor" strokeWidth="1.3"/><path d="M2 6h12M5 2v3M11 2v3" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/></svg>
  ),
  Target: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.3"/><circle cx="8" cy="8" r="3" stroke="currentColor" strokeWidth="1.3"/><circle cx="8" cy="8" r="1" fill="currentColor"/></svg>
  ),
  Lock: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><rect x="2.5" y="6" width="9" height="7" rx="1.5" stroke="currentColor" strokeWidth="1.4"/><path d="M4.5 6V4.5a2.5 2.5 0 015 0V6" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>
  ),
  Users: ({ size = 16 }) => (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none"><circle cx="6" cy="5" r="2.3" stroke="currentColor" strokeWidth="1.3"/><path d="M1.5 13c0-2.5 2-4 4.5-4s4.5 1.5 4.5 4" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/><path d="M10 6a2 2 0 100-4M13 13c0-2-1.2-3.3-3-3.8" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/></svg>
  ),
  User: ({ size = 14 }) => (
    <svg width={size} height={size} viewBox="0 0 14 14" fill="none"><circle cx="7" cy="5" r="2.3" stroke="currentColor" strokeWidth="1.4"/><path d="M2 12c0-2.2 2.2-3.6 5-3.6S12 9.8 12 12" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>
  ),
};

// ——— Tickers / Notif data ———
// Notifs type "paiement reçu" inspirées des vraies notifs Stripe / PayPal / etc.
// Prix alignés sur les packs : 799 (Premium), 199 (Starter), 499 (Pro)
// + 450 = exemple de commission d'évolution encaissée
const NOTIF_SAMPLES = [
  { src: 'Stripe',  amount: '799 €', time: 'il y a 1 min',  color: '#635bff', label: 'Pack Premium',     customer: 'Léa M.',     country: '🇫🇷' },
  { src: 'Revolut', amount: '199 €', time: 'il y a 6 min',  color: '#0a0a0b', label: 'Pack Starter',     customer: 'Karim B.',   country: '🇫🇷' },
  { src: 'PayPal',  amount: '499 €', time: 'il y a 12 min', color: '#003087', label: 'Pack Pro',         customer: 'Sofia D.',   country: '🇧🇪' },
  { src: 'Wise',    amount: '450 €', time: 'il y a 22 min', color: '#9fe870', label: 'Commission MRR',   customer: 'Évolution #124', country: '🇨🇭' },
  { src: 'Stripe',  amount: '499 €', time: 'il y a 34 min', color: '#635bff', label: 'Pack Pro',         customer: 'Thomas R.',  country: '🇫🇷' },
  { src: 'Revolut', amount: '799 €', time: 'il y a 48 min', color: '#0a0a0b', label: 'Pack Premium',     customer: 'Emma L.',    country: '🇨🇦' },
];

// ——— Landing Stats — Context & Provider ———
const _LSDefault = {
  stats:   { membres: 0, revenus: 0 },
  packs:   {
    starter: { price: 199, originalPrice: 199, commission: 25, hours: 9,  lessons: 48,  promo: null },
    pro:     { price: 499, originalPrice: 499, commission: 50, hours: 14, lessons: 144, promo: null },
    premium: { price: 799, originalPrice: 799, commission: 75, hours: 17, lessons: 250, promo: null },
  },
  academy: { modulesCount: 0, quizCount: 0, totalHours: 0, phases: [] },
  footer:  { pages: [] },
  landing: { videoUrl: '', ctaStarter: '', ctaPro: '', ctaPremium: '' },
  faq:     [],
};
const LandingStatsCtx = React.createContext(_LSDefault);

function LandingStatsProvider({ children }) {
  const [data, setData] = React.useState(_LSDefault);
  React.useEffect(() => {
    fetch('https://zrwpzetcfdpicjfdvikt.supabase.co/functions/v1/get-landing-stats')
      .then(r => r.json())
      .then(d => setData(prev => ({ ...prev, ...d })))
      .catch(() => {});
  }, []);
  return React.createElement(LandingStatsCtx.Provider, { value: data }, children);
}

function useLandingStats() { return React.useContext(LandingStatsCtx); }

Object.assign(window, {
  useState, useEffect, useRef, useLayoutEffect, useMemo, useCallback,
  useInView, Reveal, useScrollProgress, CountUp, useMagnetic, MagneticBtn, SplitText, BlurIn,
  Icon, NOTIF_SAMPLES, LandingStatsProvider, useLandingStats,
});
