// ─────────────────────────────────────────────────────────────────────────────
// WORLDLINESS — Testimonials
// Horizontal slide carousel.
// Mobile: 1 card, swipe/drag to navigate.
// Desktop (≥900px): 3 cards visible, center elevated and featured.
// Auto-advances on a shared 4s progress timeline. Touch + mouse drag supported.
// ─────────────────────────────────────────────────────────────────────────────

function Testimonials() {
  const items = window.TESTIMONIALS;
  const total = items.length;
  const AUTOPLAY_MS = 4000;

  const [idx, setIdx]           = useState(0);
  const [dragging, setDragging] = useState(false);
  const dragDeltaRef = useRef(0);   // ref so onDragEnd always reads latest value
  const dragStart    = useRef(null);
  const trackRef  = useRef(null);
  const autoRef   = useRef(null);
  const cycleStartRef = useRef(0);
  const [progress, setProgress] = useState(0);

  // ── Auto-advance ────────────────────────────────
  const [dir, setDir] = useState(1); // 1=forward, -1=backward
  const [transitioning, setTransitioning] = useState(false);

  const advance = useCallback((dir = 1, resetProgress = true) => {
    setDir(dir);
    setTransitioning(true);
    setTimeout(() => setTransitioning(false), 420);
    setIdx(i => (i + dir + total) % total);
    if (resetProgress) {
      cycleStartRef.current = performance.now();
      setProgress(0);
    }
  }, [total]);

  const startAuto = useCallback(() => {
    cancelAnimationFrame(autoRef.current);
    cycleStartRef.current = performance.now();
    setProgress(0);

    const tick = (now) => {
      const elapsed = now - cycleStartRef.current;
      const nextProgress = Math.min(elapsed / AUTOPLAY_MS, 1);
      setProgress(nextProgress);

      if (elapsed >= AUTOPLAY_MS) {
        setProgress(1);
        autoRef.current = requestAnimationFrame((then) => {
          advance(1, false);
          cycleStartRef.current = then;
          setProgress(0);
          autoRef.current = requestAnimationFrame(tick);
        });
        return;
      }

      autoRef.current = requestAnimationFrame(tick);
    };

    autoRef.current = requestAnimationFrame(tick);
  }, [advance]);

  const stopAuto = useCallback(() => {
    cancelAnimationFrame(autoRef.current);
  }, []);

  useEffect(() => {
    startAuto();
    return () => { stopAuto(); };
  }, [startAuto, stopAuto]);

  const goTo = useCallback((i) => {
    setIdx(i);
    startAuto();
  }, [startAuto]);

  // ── Drag / swipe ───────────────────────────────
  const onDragStart = useCallback((clientX) => {
    dragStart.current = clientX;
    setDragging(true);
    dragDeltaRef.current = 0;
    stopAuto();
  }, [stopAuto]);

  const onDragMove = useCallback((clientX) => {
    if (dragStart.current === null) return;
    dragDeltaRef.current = clientX - dragStart.current;
  }, []);

  const onDragEnd = useCallback(() => {
    if (dragStart.current === null) return;
    const delta = dragDeltaRef.current;
    const threshold = 60;
    if (delta < -threshold) { advance(1); startAuto(); }
    else if (delta > threshold) { advance(-1); startAuto(); }
    else startAuto();
    dragStart.current = null;
    dragDeltaRef.current = 0;
    setDragging(false);
  }, [advance, startAuto]); // no stale delta dependency

  // Mouse events
  const onMouseDown  = (e) => onDragStart(e.clientX);
  const onMouseMove  = (e) => { if (dragging) onDragMove(e.clientX); };
  const onMouseUp    = () => onDragEnd();
  const onMouseLeave = () => { if (dragging) onDragEnd(); };

  // Touch events
  const onTouchStart = (e) => onDragStart(e.touches[0].clientX);
  const onTouchMove  = (e) => onDragMove(e.touches[0].clientX);
  const onTouchEnd   = () => onDragEnd();

  // ── Keyboard nav ──────────────────────────────
  useEffect(() => {
    const k = (e) => {
      if (e.key === 'ArrowLeft')  { advance(-1); }
      if (e.key === 'ArrowRight') { advance(1); }
    };
    window.addEventListener('keydown', k);
    return () => window.removeEventListener('keydown', k);
  }, [advance]);

  // ── Helpers ────────────────────────────────────
  // Returns the item index for a given visual slot (-1, 0, +1 relative to active)
  const slotIdx = (offset) => (idx + offset + total) % total;

  return (
    <section
      className="testi"
      id="testimonials"
    >
      <div className="container">

        {/* ── Section header ── */}
        <Reveal className="testi-head">
          <Eyebrow>Client Reviews</Eyebrow>
          <h2>
            What Vancouver homeowners<br/>
            <em style={{fontStyle:'italic', fontWeight:500, color:'var(--bronze-light)'}}>say about us.</em>
          </h2>
        </Reveal>

        {/* ── Carousel track ── */}
        <Reveal>
          <div className="testi-carousel-wrap">

            {/* Prev arrow */}
            <button
              className="testi-arrow testi-arrow-prev"
              onClick={() => advance(-1)}
              aria-label="Previous review"
            >
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M19 12H5M12 19l-7-7 7-7"/>
              </svg>
            </button>

            {/* Track */}
            <div
              ref={trackRef}
              className={`testi-track ${dragging ? 'is-dragging' : ''}`}
              onMouseDown={onMouseDown}
              onMouseMove={onMouseMove}
              onMouseUp={onMouseUp}
              onMouseLeave={onMouseLeave}
              onTouchStart={onTouchStart}
              onTouchMove={onTouchMove}
              onTouchEnd={onTouchEnd}
            >
              {/* On mobile: show only active card.
                  On desktop: show prev, active (center), next. */}

              {/* Prev card — desktop only */}
              <div className="testi-slot testi-slot-prev" aria-hidden="true">
                <TestiCard item={items[slotIdx(-1)]} role="side" />
              </div>

              {/* Active card */}
              <div className="testi-slot testi-slot-active">
                <TestiCard item={items[idx]} role="active" key={idx} enterDir={dir} />
              </div>

              {/* Next card — desktop only */}
              <div className="testi-slot testi-slot-next" aria-hidden="true">
                <TestiCard item={items[slotIdx(1)]} role="side" />
              </div>
            </div>

            {/* Next arrow */}
            <button
              className="testi-arrow testi-arrow-next"
              onClick={() => advance(1)}
              aria-label="Next review"
            >
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M5 12h14M12 5l7 7-7 7"/>
              </svg>
            </button>
          </div>

          <div className="testi-controls">
            {/* ── Dot nav + counter ── */}
            <div className="testi-footer">
              <div className="testi-dots">
                {items.map((_, i) => (
                  <button
                    key={i}
                    className={`testi-dot ${i === idx ? 'active' : ''}`}
                    onClick={() => goTo(i)}
                    aria-label={`Go to review ${i + 1}`}
                  />
                ))}
              </div>
              <div className="testi-counter">
                <span className="cur">{String(idx + 1).padStart(2, '0')}</span>
                <span className="sep"> — </span>
                <span className="tot">{String(total).padStart(2, '0')}</span>
              </div>
              <div className="testi-swipe-hint">
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M5 12h14M12 5l7 7-7 7"/>
                </svg>
                <span>Swipe</span>
              </div>
            </div>

            {/* ── Bronze progress bar — driven by the same timeline as autoplay ── */}
            <div className="testi-progress-wrap" aria-hidden="true">
              <div
                className="testi-progress-fill"
                style={{ width: `${progress * 100}%` }}
              />
            </div>
          </div>
        </Reveal>

      </div>
    </section>
  );
}

// ── Single testimonial card ────────────────────────────────────────────────
function TestiCard({ item, role, enterDir = 1 }) {
  const isActive = role === 'active';
  // enterDir: 1 = entering from right, -1 = entering from left
  const enterClass = isActive ? (enterDir >= 0 ? 'enter-right' : 'enter-left') : '';
  return (
    <div className={`testi-card ${isActive ? 'active' : 'side'} ${enterClass}`}>
      <div className="testi-card-inner">
        <div className="testi-card-content">
          <div className="testi-card-quote-mark">
            <svg viewBox="0 0 32 24" fill="currentColor">
              <path d="M0 24V14.4c0-4.36 1.07-7.68 3.2-9.96C5.33 2.16 8.27.32 12.27 0v3.2c-1.87 0-3.4.87-4.6 2.6-1.2 1.74-1.8 3.87-1.8 6.4h6.4V24H0zm17.6 0V14.4c0-4.36 1.07-7.68 3.2-9.96C22.93 2.16 25.87.32 29.87 0v3.2c-1.87 0-3.4.87-4.6 2.6-1.2 1.74-1.8 3.87-1.8 6.4H30.4V24H17.6z"/>
            </svg>
          </div>
          <blockquote className="testi-card-quote">{item.quote}</blockquote>
        </div>
        <div className="testi-card-who">
          <div className="testi-card-avatar">{item.initials}</div>
          <div className="testi-card-info">
            <div className="testi-card-name">{item.name}</div>
            <div className="testi-card-meta">{item.project} · {item.location}</div>
          </div>
          <div className="testi-card-stars">★★★★★</div>
        </div>
      </div>
    </div>
  );
}

window.Testimonials = Testimonials;
