// drag-carousel.jsx — horizontal carousel with mouse-drag + momentum + snap.
// Items are case cards. Used by both variants (variant-B uses a larger card).

const { useRef: dcUseRef, useState: dcUseState, useEffect: dcUseEffect } = React;

function DragCarousel({ children, gap = 24, paddingInline = 96, height = 'auto', style }) {
  const ref = dcUseRef(null);
  const stateRef = dcUseRef({ dragging: false, startX: 0, scroll: 0, vel: 0, lastX: 0, lastT: 0 });
  const [grabbing, setGrabbing] = dcUseState(false);

  dcUseEffect(() => {
    // momentum + wheel-as-horizontal handling
    const el = ref.current;
    if (!el) return;
    let raf = 0;
    const tick = () => {
      const s = stateRef.current;
      if (!s.dragging && Math.abs(s.vel) > 0.5) {
        el.scrollLeft += s.vel;
        s.vel *= 0.93;
        raf = requestAnimationFrame(tick);
      } else {
        s.vel = 0;
      }
    };
    const onWheel = (e) => {
      // translate vertical wheel into horizontal scroll so trackpad and mouse both feel right
      if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
        el.scrollLeft += e.deltaY;
        e.preventDefault();
      }
    };
    el.addEventListener('wheel', onWheel, { passive: false });
    return () => {
      el.removeEventListener('wheel', onWheel);
      cancelAnimationFrame(raf);
    };
  }, []);

  const onDown = (e) => {
    const s = stateRef.current;
    s.dragging = true;
    s.startX = e.clientX;
    s.scroll = ref.current.scrollLeft;
    s.lastX = e.clientX;
    s.lastT = performance.now();
    s.vel = 0;
    setGrabbing(true);
    ref.current.setPointerCapture?.(e.pointerId);
  };
  const onMove = (e) => {
    const s = stateRef.current;
    if (!s.dragging) return;
    const dx = e.clientX - s.startX;
    ref.current.scrollLeft = s.scroll - dx;
    const now = performance.now();
    const dt = Math.max(1, now - s.lastT);
    s.vel = ((s.lastX - e.clientX) / dt) * 16; // px/frame
    s.lastX = e.clientX;
    s.lastT = now;
  };
  const onUp = (e) => {
    const s = stateRef.current;
    if (!s.dragging) return;
    s.dragging = false;
    setGrabbing(false);
    ref.current.releasePointerCapture?.(e.pointerId);
    // start momentum
    let raf;
    const tick = () => {
      if (Math.abs(s.vel) > 0.5) {
        ref.current.scrollLeft += s.vel;
        s.vel *= 0.93;
        raf = requestAnimationFrame(tick);
      }
    };
    if (Math.abs(s.vel) > 1) tick();
  };

  return (
    <div
      ref={ref}
      data-cursor-hover
      data-cursor-label="DRAG"
      onPointerDown={onDown}
      onPointerMove={onMove}
      onPointerUp={onUp}
      onPointerCancel={onUp}
      style={{
        display: 'flex',
        gap,
        overflowX: 'auto',
        overflowY: 'hidden',
        scrollbarWidth: 'none',
        msOverflowStyle: 'none',
        paddingInline,
        cursor: grabbing ? 'grabbing' : 'grab',
        userSelect: 'none',
        WebkitUserSelect: 'none',
        scrollBehavior: grabbing ? 'auto' : 'auto',
        height,
        ...style,
      }}
    >
      {React.Children.map(children, (child, i) => (
        <div style={{ flex: '0 0 auto', pointerEvents: grabbing ? 'none' : 'auto' }}>
          {child}
        </div>
      ))}
    </div>
  );
}

window.DragCarousel = DragCarousel;
