import { useEffect, useRef, RefObject } from 'react';

interface UseWheelNavigationProps {
  containerRef: RefObject<HTMLElement>;
  onScrollDown: () => void;
  onScrollUp: () => void;
  disabled?: boolean;
  /**
   * When the wheel event originates from inside this element,
   * skip navigation and let native scrolling happen.
   */
  excludeRef?: RefObject<HTMLElement>;
  /**
   * Minimum accumulated deltaY (px) to trigger navigation.
   * Prevents accidental triggers from trackpad micro-scrolls.
   */
  threshold?: number;
  /**
   * Cooldown in ms after a navigation fires before the next one can trigger.
   * Prevents rapid-fire scrolling from skipping multiple posts at once.
   */
  cooldownMs?: number;
}

/**
 * Triggers vertical navigation when the user scrolls (trackpad or mouse wheel)
 * over the container. Scroll down → next post, scroll up → previous post.
 *
 * Designed for the vertical player mode so the experience feels like TikTok / Reels
 * on a desktop browser.
 */
const useWheelNavigation = ({
  containerRef,
  onScrollDown,
  onScrollUp,
  disabled = false,
  excludeRef,
  threshold = 30,
  cooldownMs = 600,
}: UseWheelNavigationProps) => {
  const onScrollDownRef = useRef(onScrollDown);
  const onScrollUpRef   = useRef(onScrollUp);

  useEffect(() => {
    onScrollDownRef.current = onScrollDown;
    onScrollUpRef.current   = onScrollUp;
  }, [onScrollDown, onScrollUp]);

  useEffect(() => {
    const container = containerRef.current;
    if (!container || disabled) return;

    let accumulated = 0;
    let lastFired   = 0;

    const handleWheel = (e: WheelEvent) => {
      // Let the product list (or other excluded areas) scroll natively.
      if (excludeRef?.current && excludeRef.current.contains(e.target as Node)) {
        return;
      }

      // Prevent the page from scrolling while the player is open.
      e.preventDefault();

      const now = Date.now();
      if (now - lastFired < cooldownMs) {
        // Still in cooldown — reset accumulator so the next gesture starts fresh.
        accumulated = 0;
        return;
      }

      accumulated += e.deltaY;

      if (Math.abs(accumulated) >= threshold) {
        if (accumulated > 0) {
          onScrollDownRef.current();
        } else {
          onScrollUpRef.current();
        }
        accumulated = 0;
        lastFired   = now;
      }
    };

    // Must be non-passive so we can call preventDefault().
    container.addEventListener('wheel', handleWheel, { passive: false });
    return () => container.removeEventListener('wheel', handleWheel);
  }, [containerRef, disabled, excludeRef, threshold, cooldownMs]);
};

export default useWheelNavigation;
