import { useInfiniteQuery } from 'react-query';

import { useDebounce } from '@material-hu/hooks/useDebounce';

import usePaginatedQueryState from 'src/hooks/usePaginatedQueryState';
import { type RequestError, type RequestSuccess } from 'src/types/services';
import { sToMs } from 'src/utils/timeUtils';

import { categoriesKeys } from '../queries';
import { getCategories } from '../services';
import { type GetCategoriesParams } from '../types';

export type TSuccess = RequestSuccess<typeof getCategories>;
export type TError = RequestError;
export type TData = TSuccess;

const useGetCategories = (params: Partial<GetCategoriesParams>) => {
  const debouncedSearch = useDebounce(params.q);

  const debouncedParams: GetCategoriesParams = {
    limit: 20,
    page: 1,
    includeCourses: false,
    ...params,
    q: debouncedSearch || null,
  };

  const query = useInfiniteQuery<TSuccess, TError, TData>({
    queryKey: categoriesKeys.list.paginated(debouncedParams),
    queryFn: ({ pageParam = 1 }) =>
      getCategories({ ...debouncedParams, page: pageParam }),
    getNextPageParam: lastPage => {
      const lastPageData = lastPage.data;
      return lastPageData.page === lastPageData.totalPages
        ? undefined
        : lastPageData.page + 1;
    },
    keepPreviousData: true,
    staleTime: sToMs(60),
  });

  const { data, hasNextPage, isFetchingNextPage, fetchNextPage } = query;
  const categories = data?.pages.flatMap(page => page.data.items) || [];
  const firstCategoriesPage = data?.pages[0].data;

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

  const queryState = usePaginatedQueryState(
    firstCategoriesPage,
    query.status,
    debouncedSearch !== '',
  );

  return {
    categories,
    handleFetchNextPage,
    totalCount: firstCategoriesPage?.count ?? 0,
    queryState,
    ...query,
  };
};

export default useGetCategories;
