const { useState, useEffect, useRef } = React;
const { Reveal, useLandingStats } = window;

const Stars = ({ count = 5 }) => (
  <div style={{ display: 'flex', gap: 3 }}>
    {[...Array(count)].map((_, i) => (
      <svg key={i} width="11" height="11" viewBox="0 0 11 11" fill="var(--accent)">
        <path d="M5.5 1l1.09 3.35H9.9L7.2 6.15l1.04 3.35L5.5 7.6 2.76 9.5 3.8 6.15 1.1 4.35h3.31z"/>
      </svg>
    ))}
  </div>
);

function deriveInitial(name, fallback) {
  if (fallback && fallback.length) return fallback.slice(0, 2).toUpperCase();
  if (!name) return '??';
  const parts = name.trim().split(/\s+/);
  if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase();
  return (name[0] + (name[1] || '')).toUpperCase();
}

function TestimonialModal({ t, onClose }) {
  const [closing, setClosing] = useState(false);

  const handleClose = () => {
    setClosing(true);
    setTimeout(() => {
      setClosing(false);
      onClose();
    }, 400);
  };

  if (!t) return null;
  const initial = deriveInitial(t.name, t.initial);

  return (
    <div onClick={handleClose} style={{
      position: 'fixed', inset: 0, zIndex: 9999,
      background: 'rgba(0,0,0,0.72)',
      backdropFilter: 'blur(24px)',
      WebkitBackdropFilter: 'blur(24px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24,
      animation: closing ? 'tModalFadeOut 0.4s cubic-bezier(0.16,1,0.3,1) forwards' : 'tModalFadeIn 0.4s cubic-bezier(0.16,1,0.3,1)',
      willChange: 'opacity',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: 'var(--bg-card)',
        border: '1px solid var(--line)',
        borderRadius: 24,
        padding: '40px 48px',
        maxWidth: 700, width: '100%',
        position: 'relative',
        maxHeight: '90vh', overflowY: 'auto',
        animation: closing ? 'tModalSlideDown 0.4s cubic-bezier(0.16,1,0.3,1) forwards' : 'tModalSlideUp 0.5s cubic-bezier(0.16,1,0.3,1)',
        willChange: 'transform, opacity',
      }}>
        <button onClick={handleClose} aria-label="Fermer" data-cursor="hover" style={{
          position: 'absolute', top: 24, right: 24,
          width: 36, height: 36, borderRadius: '50%',
          background: 'var(--bg-elev)', border: '1px solid var(--line)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          cursor: 'pointer', color: 'var(--ink-mute)', fontSize: 18, lineHeight: 1,
        }}>×</button>

        <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 24 }}>
          <div style={{
            width: 48, height: 48, borderRadius: '50%', flexShrink: 0,
            background: 'color-mix(in oklab, var(--accent) 15%, var(--bg-elev))',
            border: '1px solid color-mix(in oklab, var(--accent) 28%, transparent)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontSize: 14, fontWeight: 700, color: 'var(--accent)', fontFamily: 'Geist Mono, monospace',
          }}>{initial}</div>
          <div>
            <div style={{ fontSize: 17, fontWeight: 700, color: 'var(--ink)' }}>{t.name}</div>
            <Stars count={t.rating || 5} />
          </div>
        </div>

        {t.tag && (
          <div style={{ fontSize: 22, fontWeight: 700, color: 'var(--ink)', lineHeight: 1.3, marginBottom: 20 }}>{t.tag}</div>
        )}

        <p style={{ fontSize: 16, lineHeight: 1.8, color: 'var(--ink-dim)', margin: 0 }}>
          <span style={{ fontSize: 44, lineHeight: 0, verticalAlign: '-0.35em', marginRight: 8, color: 'var(--accent)', opacity: 0.28, fontFamily: 'Georgia, serif', fontWeight: 700 }}>"</span>
          {t.fullText || t.shortText}
        </p>
      </div>
    </div>
  );
}

function TestimonialCard({ t, onOpen, width = 450, isMobile = false, isLight = false }) {
  const baseShadow = isLight
    ? '0 2px 12px rgba(0,0,0,0.04), inset 0 1px 0 rgba(255,255,255,0.9)'
    : '0 8px 32px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.5)';

  const hoverShadow = isLight
    ? '0 4px 16px rgba(0,0,0,0.05), 0 0 0 1px color-mix(in oklab, var(--accent) 15%, transparent), inset 0 1px 0 rgba(255,255,255,0.95)'
    : '0 12px 40px rgba(0,0,0,0.15), 0 0 0 1px color-mix(in oklab, var(--accent) 25%, transparent), inset 0 1px 0 rgba(255,255,255,0.6)';

  const initial = deriveInitial(t.name, t.initial);
  const previewText = t.fullText || t.shortText || '';

  return (
    <div
      onClick={onOpen}
      data-cursor="hover"
      className="testi-card"
      style={{
        flexShrink: 0, width,
        background: 'color-mix(in oklab, var(--bg-card) 72%, transparent)',
        backdropFilter: 'blur(28px) saturate(1.5)',
        WebkitBackdropFilter: 'blur(28px) saturate(1.5)',
        border: '1px solid color-mix(in oklab, var(--line) 50%, transparent)',
        boxShadow: baseShadow,
        borderRadius: 20, padding: isMobile ? '14px 14px 12px' : '26px 28px 24px',
        display: 'flex', flexDirection: 'column', gap: 0,
        position: 'relative', overflow: 'hidden',
        cursor: 'pointer',
        transition: 'box-shadow 0.3s ease, border-color 0.3s ease',
      }}
      onMouseEnter={e => { e.currentTarget.style.boxShadow = hoverShadow; }}
      onMouseLeave={e => { e.currentTarget.style.boxShadow = baseShadow; }}
    >
      <div style={{ position: 'absolute', top: isMobile ? -40 : -60, left: isMobile ? -40 : -60, width: isMobile ? 120 : 180, height: isMobile ? 120 : 180, borderRadius: '50%', background: 'var(--accent)', opacity: 0.05, filter: 'blur(30px)', pointerEvents: 'none' }} />
      <div style={{ position: 'absolute', top: '20%', left: 0, width: 2, height: '60%', borderRadius: 2, background: 'linear-gradient(to bottom, transparent, var(--accent), transparent)', opacity: 0.6 }} />

      <div style={{
        position: 'absolute', top: 16, right: 16,
        width: 26, height: 26, borderRadius: 8,
        background: 'color-mix(in oklab, var(--accent) 12%, transparent)',
        border: '1px solid color-mix(in oklab, var(--accent) 22%, transparent)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="var(--accent)" strokeWidth="1.5" strokeLinecap="round">
          <path d="M4.5 1.5H1.5v3M7.5 1.5h3v3M4.5 10.5H1.5v-3M7.5 10.5h3v-3"/>
        </svg>
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 13, paddingRight: 40, marginBottom: 16 }}>
        <div style={{
          width: 44, height: 44, borderRadius: '50%', flexShrink: 0,
          background: 'linear-gradient(135deg, color-mix(in oklab, var(--accent) 22%, var(--bg-elev)), var(--bg-elev))',
          border: '1px solid color-mix(in oklab, var(--accent) 28%, transparent)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 12, fontWeight: 700, color: 'var(--accent)', fontFamily: 'Geist Mono, monospace',
          boxShadow: '0 0 12px color-mix(in oklab, var(--accent) 20%, transparent)',
        }}>{initial}</div>
        <div>
          <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink)', lineHeight: 1.1, marginBottom: 4 }}>{t.name}</div>
          <Stars count={t.rating || 5} />
        </div>
      </div>

      <div style={{ height: 1, background: 'linear-gradient(to right, var(--accent), color-mix(in oklab, var(--accent) 20%, transparent))', marginBottom: 14, opacity: 0.35 }} />

      {t.tag && (
        <div style={{ fontSize: 15, fontWeight: 800, color: 'var(--ink)', lineHeight: 1.3, letterSpacing: '-0.01em', marginBottom: 12 }}>{t.tag}</div>
      )}

      <div style={{ position: 'relative', flex: 1 }}>
        <p style={{
          fontSize: 15, lineHeight: 1.75, color: 'var(--ink-dim)',
          fontStyle: 'italic',
          overflow: 'hidden', display: '-webkit-box',
          WebkitBoxOrient: 'vertical', WebkitLineClamp: 4, margin: 0,
        }}>
          <span style={{ fontSize: 42, lineHeight: 0, verticalAlign: '-0.38em', marginRight: 4, color: 'var(--accent)', opacity: 0.25, fontFamily: 'Georgia, serif', fontStyle: 'normal', fontWeight: 700 }}>"</span>
          {previewText}
        </p>
        <div style={{
          position: 'absolute', bottom: 0, left: 0, right: 0, height: 38,
          background: 'linear-gradient(to top, color-mix(in oklab, var(--bg-card) 72%, transparent) 0%, transparent 100%)',
          pointerEvents: 'none',
        }} />
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 16 }}>
        <svg width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="var(--accent)" strokeWidth="1.5" strokeLinecap="round">
          <path d="M4.5 1.5H1.5v3M7.5 1.5h3v3M4.5 10.5H1.5v-3M7.5 10.5h3v-3"/>
        </svg>
        <span style={{ fontSize: 11, color: 'var(--accent)', fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase' }}>Lire l'avis complet</span>
      </div>
    </div>
  );
}

const CARD_WIDTH_DESKTOP = 450;
const CARD_WIDTH_MOBILE  = 200;
const CARD_GAP_DESKTOP   = 16;
const CARD_GAP_MOBILE    = 10;
const SPEED              = 0.4; // px/frame, défilement très lent
const MOBILE_BREAKPOINT  = 768;

/* Une rangée auto-scrollante — animation et duplication encapsulées par row */
function TestimonialRow({ list, dir, baseSpeed, vw, cardWidth, cardGap, cardTotal, isMobile, isLight, isPaused, onOpenModal }) {
  const rowRef = useRef(null);
  const pos = useRef(null);
  const speed = useRef(baseSpeed);
  const targetSpeed = useRef(baseSpeed);
  const isHovering = useRef(false);
  const rafRef = useRef(null);

  const ONE_COPY_WIDTH = list.length * cardTotal;
  const repeats = Math.max(3, Math.ceil((vw + ONE_COPY_WIDTH) / ONE_COPY_WIDTH) + 1);
  const ROW = Array.from({ length: repeats }, () => list).flat();
  const ROW_WIDTH = ONE_COPY_WIDTH;

  useEffect(() => {
    const lerp = (a, b, t) => a + (b - a) * t;
    const mod = (n, m) => ((n % m) + m) % m;

    if (pos.current === null) {
      pos.current = -ONE_COPY_WIDTH;
      if (rowRef.current) rowRef.current.style.transform = `translateX(${pos.current}px)`;
    }

    const loop = () => {
      const currentTarget = isHovering.current || isPaused ? 0 : baseSpeed;
      targetSpeed.current = currentTarget;
      speed.current = lerp(speed.current, targetSpeed.current, 0.035);
      if (currentTarget === 0 && Math.abs(speed.current) < 0.05) speed.current = 0;

      pos.current += dir * speed.current;
      pos.current = mod(pos.current, ROW_WIDTH) - ROW_WIDTH;
      if (rowRef.current) rowRef.current.style.transform = `translateX(${pos.current}px)`;

      rafRef.current = requestAnimationFrame(loop);
    };
    rafRef.current = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(rafRef.current);
  }, [ROW_WIDTH, isPaused, dir, baseSpeed]);

  return (
    <div
      ref={rowRef}
      className="testi-row"
      onMouseEnter={() => { isHovering.current = true; }}
      onMouseLeave={() => { isHovering.current = false; }}
      style={{ display: 'flex', gap: cardGap, willChange: 'transform' }}
    >
      {ROW.map((t, i) => (
        <TestimonialCard key={i} t={t} onOpen={() => onOpenModal(t)} width={cardWidth} isMobile={isMobile} isLight={isLight} />
      ))}
    </div>
  );
}

function TestimonialsSection() {
  const { testimonials } = useLandingStats();
  const [modal, setModal] = useState(null);
  const [vw, setVw] = useState(() => typeof window !== 'undefined' ? window.innerWidth : 1920);
  const [isLight, setIsLight] = useState(false);

  // Resize débouncé (200 ms) — sinon chaque event remonte les TestimonialRow et casse l'animation
  useEffect(() => {
    let timeout;
    const onResize = () => {
      clearTimeout(timeout);
      timeout = setTimeout(() => setVw(window.innerWidth), 200);
    };
    window.addEventListener('resize', onResize, { passive: true });
    return () => { window.removeEventListener('resize', onResize); clearTimeout(timeout); };
  }, []);

  // Single MutationObserver pour le thème, partagé par toutes les cartes
  useEffect(() => {
    const check = () => setIsLight(document.documentElement.getAttribute('data-theme') === 'light');
    check();
    const obs = new MutationObserver(check);
    obs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
    return () => obs.disconnect();
  }, []);

  const list = Array.isArray(testimonials) ? testimonials : [];
  const hasEnough = list.length > 0;

  // Tailles dépendantes du viewport — JS et CSS doivent rester alignés
  const isMobile = vw < MOBILE_BREAKPOINT;
  const CARD_WIDTH = isMobile ? CARD_WIDTH_MOBILE : CARD_WIDTH_DESKTOP;
  const CARD_GAP   = isMobile ? CARD_GAP_MOBILE   : CARD_GAP_DESKTOP;
  const CARD_TOTAL = CARD_WIDTH + CARD_GAP;

  // Décide si on passe à 2 rangées : si la liste totale excède 1.5 viewport,
  // un défilement seul devient long et monotone → on splitte.
  // Il faut aussi au moins 4 avis pour que 2 rangées de 2 aient du sens.
  const totalListWidth = list.length * CARD_TOTAL;
  const useTwoRows = hasEnough && list.length >= 4 && totalListWidth > vw * 1.5;

  const rows = useTwoRows
    ? [
        list.filter((_, i) => i % 2 === 0),
        list.filter((_, i) => i % 2 === 1),
      ]
    : [list];

  if (!hasEnough) return null;

  return (
    <section className="section section-soft" id="testimonials">
      <div className="container">
        <Reveal className="section-header" style={{ textAlign: 'center', alignItems: 'center', marginLeft: 'auto', marginRight: 'auto' }}>
          <h2 className="h2" style={{ textTransform: 'none' }}>
            Ceux qui ont commencé<br />
            <span className="serif-i" style={{ color: 'var(--accent)', fontWeight: 400 }}>avant toi dans VIZION.</span>
          </h2>
          <p style={{ color: 'var(--ink-dim)', fontSize: 17, maxWidth: 560, marginTop: 16, lineHeight: 1.7 }}>
            Des vrais témoignages de membres qui utilisent VIZION pour bâtir leur liberté.
            Je te laisse voir leur avis.
          </p>
        </Reveal>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12, overflow: 'hidden', position: 'relative' }}>
        <div style={{
          position: 'absolute', top: 0, left: 0, bottom: 0, width: 120, zIndex: 2, pointerEvents: 'none',
          background: 'linear-gradient(to right, var(--bg) 0%, transparent 100%)',
        }} />
        <div style={{
          position: 'absolute', top: 0, right: 0, bottom: 0, width: 120, zIndex: 2, pointerEvents: 'none',
          background: 'linear-gradient(to left, var(--bg) 0%, transparent 100%)',
        }} />

        {rows.map((rowList, idx) => (
          <TestimonialRow
            key={`${idx}-${rowList.length}-${vw}-${useTwoRows ? 2 : 1}`}
            list={rowList}
            // 1ère rangée gauche→droite (dir +1) ; 2e rangée droite→gauche (dir -1) pour effet V8
            dir={idx === 0 ? 1 : -1}
            baseSpeed={idx === 0 ? SPEED : SPEED * 0.85}
            vw={vw}
            cardWidth={CARD_WIDTH}
            cardGap={CARD_GAP}
            cardTotal={CARD_TOTAL}
            isMobile={isMobile}
            isLight={isLight}
            isPaused={!!modal}
            onOpenModal={setModal}
          />
        ))}
      </div>

      <TestimonialModal t={modal} onClose={() => setModal(null)} />

      <style>{`
        @keyframes tModalSlideUp {
          0%   { opacity: 0; transform: translateY(32px) scale(0.94); filter: blur(4px); }
          60%  { opacity: 1; filter: blur(0); }
          100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
        }
        @keyframes tModalFadeIn {
          from { opacity: 0; backdrop-filter: blur(0px); }
          to   { opacity: 1; backdrop-filter: blur(24px); }
        }
        @keyframes tModalFadeOut {
          from { opacity: 1; backdrop-filter: blur(24px); }
          to   { opacity: 0; backdrop-filter: blur(0px); }
        }
        @keyframes tModalSlideDown {
          0%   { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
          40%  { opacity: 1; filter: blur(2px); }
          100% { opacity: 0; transform: translateY(32px) scale(0.94); filter: blur(4px); }
        }
        /* Plus de override CSS — la largeur des cartes est gérée en inline style depuis le JS pour rester synchro avec le calcul du cycle d'animation */
      `}</style>
    </section>
  );
}

Object.assign(window, { TestimonialsSection });
