import { IsResponseAListDTO } from "@shared/contexts";
import {
  QueryFunctionContext,
  QueryKey,
  UseQueryResult,
  keepPreviousData,
  useQuery,
} from "@tanstack/react-query";

import { useEffect, useState } from "react";

import {
  UseLoadingOvertimeOptionsProps,
  UseLoadingOvertimeReturnType,
  useLoadingOvertime,
} from "../useLoadingOvertime/useLoadingOvertime";

const DEFAULT_REFETCH_INTERVAL = 2 * 60 * 1000; // 2 minutes
const DEFAULT_STALE_TIME = 60 * 1000; // 1 minute

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export type UseListQueryOptions<TUseListQueryData, _TUseListQueryError> = {
  queryKey: QueryKey;
  queryFn: (context: QueryFunctionContext) => Promise<TUseListQueryData>;
  enabled?: boolean;
  select?: (data: TUseListQueryData) => TUseListQueryData;
  queryOptions?: Record<string, unknown>;
} & UseLoadingOvertimeOptionsProps;

export type UseListQueryResult<TUseListQueryData, TUseListQueryError> = UseQueryResult<
  TUseListQueryData,
  TUseListQueryError
> & {
  isEmpty: boolean;
} & UseLoadingOvertimeReturnType;

export const useList = <TUseListQueryData, TUseListQueryError>({
  queryKey,
  queryFn,
  enabled,
  select,
  queryOptions = {},
  overtimeOptions,
}: UseListQueryOptions<TUseListQueryData, TUseListQueryError>): UseListQueryResult<
  TUseListQueryData,
  TUseListQueryError
> => {
  const [isEmpty, setIsEmpty] = useState<boolean>(false);

  const queryResponse = useQuery<TUseListQueryData, TUseListQueryError>({
    queryKey,
    queryFn,
    placeholderData: keepPreviousData,
    staleTime: DEFAULT_STALE_TIME,
    refetchInterval: DEFAULT_REFETCH_INTERVAL,
    refetchOnWindowFocus: true,
    enabled: enabled && !!queryFn,
    select,
    ...queryOptions,
  });

  useEffect(() => {
    if (queryResponse.isSuccess && IsResponseAListDTO(queryResponse.data)) {
      setIsEmpty(queryResponse.data.total_items === 0);
    }
  }, [queryResponse]);

  const { elapsedTime } = useLoadingOvertime({
    isPending: queryResponse.isFetching,
    interval: overtimeOptions?.interval,
    onInterval: overtimeOptions?.onInterval,
  });

  const result = {
    ...queryResponse,
    overtime: { elapsedTime },
    isEmpty,
  };
  return result;
};
