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

import { isResponseAListDTO } from "../../../common/dto";
import {
  UseLoadingOvertimeOptionsProps,
  UseLoadingOvertimeReturnType,
  useLoadingOvertime,
} from "./use-loading-overtime";

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;
  refetchInterval?: number | false;
  select?: (data: TUseListQueryData) => TUseListQueryData;
  queryOptions?: Partial<UseQueryOptions<TUseListQueryData, TUseListQueryError>>;
} & UseLoadingOvertimeOptionsProps;

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

/**
 * Hook para manejar consultas de listas con React Query,
 * incluye detección de listas vacías y control de sobretiempo de carga.
 */
export const useList = <TUseListQueryData, TUseListQueryError>({
  queryKey,
  queryFn,
  enabled,
  refetchInterval,
  select,
  queryOptions = {},
  overtimeOptions,
}: UseListQueryOptions<TUseListQueryData, TUseListQueryError>): UseListQueryResult<
  TUseListQueryData,
  TUseListQueryError
> => {
  if (!queryFn) {
    console.error("queryFn es requerido en useList");
    throw new Error("queryFn es requerido en useList");
  }

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

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

  const isEmpty =
    queryResponse.isSuccess &&
    isResponseAListDTO(queryResponse.data) &&
    queryResponse.data.total_items === 0;

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