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

interface UseVirtualScrollOptions {
  itemCount: number;
  itemHeight: number;
  overscan?: number;
  containerHeight: number;
}

interface VirtualScrollState {
  startIndex: number;
  endIndex: number;
  offsetY: number;
  visibleCount: number;
}

export function useVirtualScroll({
  itemCount,
  itemHeight,
  overscan = 5,
  containerHeight,
}: UseVirtualScrollOptions) {
  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef<HTMLDivElement>(null);

  const totalHeight = itemCount * itemHeight;
  const visibleCount = Math.ceil(containerHeight / itemHeight);
  const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
  const endIndex = Math.min(itemCount, startIndex + visibleCount + overscan * 2);
  const offsetY = startIndex * itemHeight;

  const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
    setScrollTop(e.currentTarget.scrollTop);
  }, []);

  const scrollToIndex = useCallback((index: number) => {
    if (containerRef.current) {
      containerRef.current.scrollTop = index * itemHeight;
    }
  }, [itemHeight]);

  return {
    containerRef,
    startIndex,
    endIndex,
    offsetY,
    totalHeight,
    visibleCount,
    handleScroll,
    scrollToIndex,
  };
}

// 分页加载 Hook
interface UsePaginationOptions<T> {
  items: T[];
  pageSize: number;
  initialPage?: number;
}

interface PaginationState<T> {
  currentPage: number;
  totalPages: number;
  paginatedItems: T[];
  hasNextPage: boolean;
  hasPrevPage: boolean;
}

interface PaginationActions {
  goToPage: (page: number) => void;
  goToNextPage: () => void;
  goToPrevPage: () => void;
  goToFirstPage: () => void;
  goToLastPage: () => void;
}

export function usePagination<T>({
  items,
  pageSize,
  initialPage = 1,
}: UsePaginationOptions<T>): PaginationState<T> & PaginationActions {
  const [currentPage, setCurrentPage] = useState(initialPage);

  const totalPages = Math.ceil(items.length / pageSize);
  const startIndex = (currentPage - 1) * pageSize;
  const endIndex = startIndex + pageSize;
  const paginatedItems = items.slice(startIndex, endIndex);

  const goToPage = useCallback(
    (page: number) => {
      if (page >= 1 && page <= totalPages) {
        setCurrentPage(page);
      }
    },
    [totalPages]
  );

  const goToNextPage = useCallback(() => {
    if (currentPage < totalPages) {
      setCurrentPage((p) => p + 1);
    }
  }, [currentPage, totalPages]);

  const goToPrevPage = useCallback(() => {
    if (currentPage > 1) {
      setCurrentPage((p) => p - 1);
    }
  }, [currentPage]);

  const goToFirstPage = useCallback(() => {
    setCurrentPage(1);
  }, []);

  const goToLastPage = useCallback(() => {
    setCurrentPage(totalPages);
  }, [totalPages]);

  // Reset to first page when items change
  useEffect(() => {
    setCurrentPage(1);
  }, [items.length]);

  return {
    currentPage,
    totalPages,
    paginatedItems,
    hasNextPage: currentPage < totalPages,
    hasPrevPage: currentPage > 1,
    goToPage,
    goToNextPage,
    goToPrevPage,
    goToFirstPage,
    goToLastPage,
  };
}

// 无限滚动 Hook
interface UseInfiniteScrollOptions<T> {
  fetchData: (page: number) => Promise<T[]>;
  pageSize: number;
  threshold?: number;
}

interface InfiniteScrollState<T> {
  items: T[];
  loading: boolean;
  hasMore: boolean;
  error: Error | null;
}

interface InfiniteScrollActions {
  loadMore: () => void;
  refresh: () => void;
  reset: () => void;
}

export function useInfiniteScroll<T>({
  fetchData,
  pageSize,
  threshold = 100,
}: UseInfiniteScrollOptions<T>): InfiniteScrollState<T> & InfiniteScrollActions {
  const [items, setItems] = useState<T[]>([]);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [error, setError] = useState<Error | null>(null);
  const [page, setPage] = useState(1);
  const loadingRef = useRef(false);

  const loadData = useCallback(
    async (pageNum: number, append: boolean = false) => {
      if (loadingRef.current) return;
      loadingRef.current = true;
      setLoading(true);
      setError(null);

      try {
        const newItems = await fetchData(pageNum);
        if (newItems.length < pageSize) {
          setHasMore(false);
        }
        if (append) {
          setItems((prev) => [...prev, ...newItems]);
        } else {
          setItems(newItems);
        }
      } catch (err) {
        setError(err as Error);
      } finally {
        setLoading(false);
        loadingRef.current = false;
      }
    },
    [fetchData, pageSize]
  );

  const loadMore = useCallback(() => {
    if (!loading && hasMore) {
      setPage((p) => p + 1);
      loadData(page + 1, true);
    }
  }, [loading, hasMore, page, loadData]);

  const refresh = useCallback(() => {
    setPage(1);
    setHasMore(true);
    loadData(1, false);
  }, [loadData]);

  const reset = useCallback(() => {
    setItems([]);
    setPage(1);
    setHasMore(true);
    setError(null);
  }, []);

  // Initial load
  useEffect(() => {
    loadData(1, false);
  }, [loadData]);

  return {
    items,
    loading,
    hasMore,
    error,
    loadMore,
    refresh,
    reset,
  };
}

// 防抖滚动 Hook
export function useDebouncedScroll(callback: () => void, delay: number = 100) {
  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const handleScroll = useCallback(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }
    timeoutRef.current = setTimeout(callback, delay);
  }, [callback, delay]);

  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, []);

  return handleScroll;
}
