import { useMemoizedFn } from 'ahooks';
import { useEffect, useRef, useState } from 'react';

interface UseInfiniteScrollOptions {
  /**
   * 是否有更多数据可以加载
   */
  hasNextPage: boolean;
  /**
   * 是否正在加载
   */
  isLoading: boolean;
  /**
   * 加载下一页的函数
   */
  fetchNextPage: () => void;
  /**
   * 触发加载的阈值(px)，当距离容器底部多少像素时触发加载
   */
  threshold?: number;
  /**
   * 是否启用（默认为true）
   */
  enabled?: boolean;
  /**
   * 是否有错误
   */
  isError?: boolean;
}

/**
 * 无限滚动Hook
 * 支持向下滚动和向上滚动加载更多
 */
export function useInfiniteScroll({
  hasNextPage,
  isLoading,
  fetchNextPage,
  threshold = 200,
  enabled = true,
  isError = false,
}: UseInfiniteScrollOptions) {
  const [isFetching, setIsFetching] = useState(false);
  const observerRef = useRef<IntersectionObserver | null>(null);
  const loadMoreRef = useRef<HTMLDivElement>(null);

  // 加载更多数据
  const loadMore = useMemoizedFn(async () => {
    // 如果有错误，不继续加载
    if (!hasNextPage || isLoading || isFetching || isError) return;

    setIsFetching(true);
    try {
      fetchNextPage();
    } finally {
      // 延迟重置状态，避免快速重复触发
      setTimeout(() => {
        setIsFetching(false);
      }, 100);
    }
  });

  // 设置Intersection Observer
  useEffect(() => {
    if (!enabled || !loadMoreRef.current) return;

    const options = {
      root: null,
      rootMargin: `${threshold}px`,
      threshold: 0.1,
    };

    observerRef.current = new IntersectionObserver((entries) => {
      const [entry] = entries;

      if (entry.isIntersecting) {
        loadMore();
      }
    }, options);

    const currentRef = loadMoreRef.current;
    if (currentRef) {
      observerRef.current.observe(currentRef);
    }

    return () => {
      if (observerRef.current && currentRef) {
        observerRef.current.unobserve(currentRef);
      }
    };
  }, [enabled, threshold, loadMore, !!loadMoreRef.current]);

  // 清理observer
  useEffect(() => {
    return () => {
      if (observerRef.current) {
        observerRef.current.disconnect();
      }
    };
  }, []);

  return {
    loadMoreRef,
    isFetching,
    loadMore,
  };
}
