"use client";

import { useCallback, useEffect, useRef, useState } from "react";

interface PullToRefreshOptions {
  onRefresh: () => void | Promise<void>;
  threshold?: number;
  enabled?: boolean;
}

interface PullToRefreshResult {
  pullDistance: number;
  isRefreshing: boolean;
  pullPercent: number;
}

/**
 * Pull-to-refresh hook for mobile H5 pages.
 * Attaches touch listeners to the document body and triggers `onRefresh`
 * when the user pulls down past `threshold` while scrolled to top.
 */
export function usePullToRefresh({
  onRefresh,
  threshold = 70,
  enabled = true,
}: PullToRefreshOptions): PullToRefreshResult {
  const [pullDistance, setPullDistance] = useState(0);
  const [isRefreshing, setIsRefreshing] = useState(false);
  const startYRef = useRef(0);
  const pullingRef = useRef(false);
  const pullDistanceRef = useRef(0);
  const onRefreshRef = useRef(onRefresh);

  onRefreshRef.current = onRefresh;

  const handleTouchStart = useCallback(
    (e: TouchEvent) => {
      if (!enabled || isRefreshing) return;
      
      // Check if the scroll container is scrolled down
      const scrollContainer = document.getElementById("player-scroll-container");
      const currentScrollY = scrollContainer ? scrollContainer.scrollTop : window.scrollY;
      
      if (currentScrollY > 0) return;
      startYRef.current = e.touches[0].clientY;
      pullingRef.current = true;
    },
    [enabled, isRefreshing],
  );

  const handleTouchMove = useCallback(
    (e: TouchEvent) => {
      if (!pullingRef.current || isRefreshing) return;
      const delta = e.touches[0].clientY - startYRef.current;
      if (delta <= 0) {
        // User is scrolling down — abort pull-to-refresh entirely
        pullingRef.current = false;
        if (pullDistanceRef.current !== 0) {
          pullDistanceRef.current = 0;
          setPullDistance(0);
        }
        return;
      }
      // Apply rubber-band resistance
      const resisted = Math.min(delta * 0.4, threshold * 1.5);
      if (resisted !== pullDistanceRef.current) {
        pullDistanceRef.current = resisted;
        setPullDistance(resisted);
      }
    },
    [isRefreshing, threshold],
  );

  const handleTouchEnd = useCallback(async () => {
    if (!pullingRef.current) {
      if (pullDistanceRef.current !== 0) {
        pullDistanceRef.current = 0;
        setPullDistance(0);
      }
      return;
    }
    pullingRef.current = false;

    if (pullDistanceRef.current >= threshold) {
      setIsRefreshing(true);
      pullDistanceRef.current = threshold * 0.5;
      setPullDistance(threshold * 0.5);
      try {
        await onRefreshRef.current();
      } finally {
        setIsRefreshing(false);
        pullDistanceRef.current = 0;
        setPullDistance(0);
      }
    } else {
      pullDistanceRef.current = 0;
      setPullDistance(0);
    }
  }, [threshold]);

  useEffect(() => {
    if (!enabled) return;

    document.addEventListener("touchstart", handleTouchStart, { passive: true });
    document.addEventListener("touchmove", handleTouchMove, { passive: true });
    document.addEventListener("touchend", handleTouchEnd, { passive: true });

    return () => {
      document.removeEventListener("touchstart", handleTouchStart);
      document.removeEventListener("touchmove", handleTouchMove);
      document.removeEventListener("touchend", handleTouchEnd);
    };
  }, [enabled, handleTouchStart, handleTouchMove, handleTouchEnd]);

  return {
    pullDistance,
    isRefreshing,
    pullPercent: Math.min(pullDistance / threshold, 1),
  };
}
