import { useInfiniteQuery } from "@tanstack/react-query";
import { useMemo, useCallback } from "react";

export interface InfiniteScrollConfig<TData, TParams = Record<string, any>> {
  queryKey: any[];
  queryFn: (params: { pageParam: number } & TParams) => Promise<{
    data: TData[];
    total?: number;
    hasMore?: boolean;
  }>;
  initialPageParam?: number;
  getNextPageParam?: (lastPage: any, allPages: any[], lastPageParam: number) => number | undefined;
  pageSize?: number;
  enabled?: boolean;
  staleTime?: number;
  params?: TParams;
}

export function useInfiniteScroll<TData, TParams = Record<string, any>>({
  queryKey,
  queryFn,
  initialPageParam = 1,
  getNextPageParam,
  pageSize = 20,
  enabled = true,
  staleTime = 5 * 60 * 1000, // 5분
  params = {} as TParams,
}: InfiniteScrollConfig<TData, TParams>) {
  // React Query의 useInfiniteQuery 사용
  const infiniteQuery = useInfiniteQuery({
    queryKey: [...queryKey, params],
    queryFn: ({ pageParam }) => queryFn({ pageParam, ...params }),
    initialPageParam,
    getNextPageParam:
      getNextPageParam ||
      ((lastPage, allPages, lastPageParam) => {
        // 기본 페이지네이션 로직
        if (lastPage.data.length < pageSize) {
          return undefined; // 더 이상 페이지 없음
        }
        return lastPageParam + 1;
      }),
    enabled,
    staleTime,
  });

  // 모든 페이지의 데이터를 평탄화
  const flatData = useMemo(() => {
    if (!infiniteQuery.data?.pages) return [];

    const allData = infiniteQuery.data.pages.flatMap((page) => page.data);

    // 중복 제거 - code_value 또는 category_code를 기준으로
    const uniqueData = allData.filter((item, index, self) => {
      const key = (item as any).code_value || (item as any).category_code;
      if (!key) return true; // key가 없으면 그대로 유지

      return (
        index ===
        self.findIndex((t) => {
          const tKey = (t as any).code_value || (t as any).category_code;
          return tKey === key;
        })
      );
    });

    return uniqueData;
  }, [infiniteQuery.data]);

  // 총 개수 계산 (첫 번째 페이지의 total 사용)
  const totalCount = useMemo(() => {
    return infiniteQuery.data?.pages[0]?.total || 0;
  }, [infiniteQuery.data]);

  // 다음 페이지 로드 함수
  const loadMore = useCallback(() => {
    if (infiniteQuery.hasNextPage && !infiniteQuery.isFetchingNextPage) {
      infiniteQuery.fetchNextPage();
    }
  }, [infiniteQuery]);

  // 스크롤 이벤트 핸들러
  const handleScroll = useCallback(
    (e: React.UIEvent<HTMLDivElement>) => {
      const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;

      // 스크롤이 하단에서 100px 이내에 도달하면 다음 페이지 로드
      if (scrollHeight - scrollTop <= clientHeight + 100) {
        loadMore();
      }
    },
    [loadMore],
  );

  // 무한 스크롤 상태 정보
  const infiniteScrollState = {
    // 데이터
    data: flatData,
    totalCount,

    // 로딩 상태
    isLoading: infiniteQuery.isLoading,
    isFetchingNextPage: infiniteQuery.isFetchingNextPage,
    hasNextPage: infiniteQuery.hasNextPage,

    // 에러 상태
    error: infiniteQuery.error,
    isError: infiniteQuery.isError,

    // 기타 상태
    isSuccess: infiniteQuery.isSuccess,
    isFetching: infiniteQuery.isFetching,
  };

  return {
    ...infiniteScrollState,
    loadMore,
    handleScroll,
    refetch: infiniteQuery.refetch,
    invalidate: infiniteQuery.refetch,
  };
}

// 편의를 위한 타입 정의
export type InfiniteScrollReturn<TData> = ReturnType<typeof useInfiniteScroll<TData>>;
