import { keepPreviousData, useInfiniteQuery } from '@tanstack/react-query';
import { useMemo, useState } from 'react';

type ParamsType<Q = any> = {
  index: number;
  limit: number;
  query: Q;
};

type PropsType<Q = any> = {
  queryKey: string;
  defaultQuery?: Q;
  defaultIndex?: number;
  limit?: number;
  enabled?: boolean; // 是否启用查询
};

type RequestType<T = any, Q = any> = (
  params: ParamsType<Q>
) => Promise<{ rows: T[]; total: number } | undefined>;

type UseInfiniteScrollValue<T = any, Q = any> = {
  query: Q;
  onLoadMore: () => void;
  onSearch: (query: Q) => void;
  dataSource: T[];
  total: number;
  // 是否正在加载第一页，包括 初始化加载 和 参数改变时加载
  isFirstLoading: boolean;
  isLoadingMore: boolean;
  refresh: () => void;
  noMoreData: boolean;
  error: Error | null;
};

export const useInfiniteScroll = <T = any, Q = any>(
  request: RequestType<T, Q>,
  props: PropsType<Q>
): UseInfiniteScrollValue<T, Q> => {
  const {
    queryKey,
    defaultQuery,
    defaultIndex = 1,
    limit = 20,
    enabled = true,
  } = props;

  const [query, setQuery] = useState<Q>(defaultQuery as Q);

  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetching,
    isFetchingNextPage,
    isLoading,
    refetch,
    error,
  } = useInfiniteQuery({
    queryKey: [queryKey, query],
    queryFn: async ({ pageParam = 1 }) => {
      if (!request) {
        return { rows: [], total: 0 };
      }
      const params = {
        limit,
        index: pageParam,
        query,
      };

      // 修复：添加错误处理
      try {
        const result = await request(params);
        return result || { rows: [], total: 0 };
      } catch (err) {
        console.error('useInfiniteScroll request error:', err);
        throw err; // 让 React Query 处理错误
      }
    },
    getNextPageParam: (lastPage, allPages) => {
      const currentTotal = limit * allPages.length;
      if (currentTotal < lastPage.total) {
        return allPages.length + 1;
      }
      // 没有下一页
      return undefined;
    },
    initialPageParam: defaultIndex,
    enabled: enabled && !!request,
    placeholderData: keepPreviousData, // 保留旧数据直到新数据加载完成
  });

  // 合并所有页面的数据
  const dataSource = useMemo(() => {
    return data?.pages.flatMap((page) => page.rows || []) || [];
  }, [data]);

  const total = useMemo(() => {
    return data?.pages[0]?.total || 0;
  }, [data?.pages]);

  const onLoadMore = () => {
    if (hasNextPage && !isFetchingNextPage) {
      fetchNextPage();
    }
  };

  return {
    query,
    onLoadMore,
    onSearch: setQuery,
    dataSource,
    total,
    isFirstLoading: isLoading || (isFetching && !isFetchingNextPage),
    isLoadingMore: isFetchingNextPage,
    refresh: () => refetch(),
    noMoreData: !hasNextPage,
    error: error as Error | null,
  };
};
