import { UseQueryResult, useQueries } from "@tanstack/react-query";
import { fetchList } from "../api";
import { useGetCurrencyDataQuery } from "../state-manager/api";
import { currencyFormatter } from "../utils/currencyFormatter";
import { QUERY_KEY } from "../utils/queryKeys";
import { REFETCH_TIME_ONE_MINUTE, BASIC_REFETCH } from "../utils/timers";
import {
  MarketCurrencyRequestParams,
  MarketListRequestParams,
  MarketCurrencyData,
  HashMapBody,
  MarketItemResponse,
  MarketListRequestResult,
  Order,
} from "../utils/types";

export const useCurrencyData = ({ id, counterCurrency }: MarketCurrencyRequestParams) =>
  useGetCurrencyDataQuery(
    { id, counterCurrency },
    {
      pollingInterval: REFETCH_TIME_ONE_MINUTE * BASIC_REFETCH,
    },
  );

export function useMarketData(props: MarketListRequestParams): MarketListRequestResult {
  const search = props.search?.toLowerCase() ?? "";
  return useQueries({
    queries: Array.from({ length: props.page ?? 1 }, (_, i) => i).map(page => ({
      queryKey: [
        QUERY_KEY.MarketData,
        page,
        props.order,
        {
          counterCurrency: props.counterCurrency,
          ...(props.search && props.search?.length >= 2 && { search: search }),
          ...(props.starred && props.starred?.length >= 1 && { starred: props.starred }),
          ...(props.liveCompatible && { liveCompatible: props.liveCompatible }),
          ...(props.order &&
            [Order.topLosers, Order.topGainers].includes(props.order) && { range: props.range }),
        },
      ],
      queryFn: () => fetchList({ ...props, page, search }),
      select: (data: MarketItemResponse[]) => ({
        formattedData: currencyFormatter(data),
        page,
      }),
      refetchOnMount: false,
      refetchOnReconnect: true,
      refetchOnWindowFocus: false,
    })),
    combine: combineMarketData,
  });
}

function combineMarketData(
  results: UseQueryResult<
    {
      formattedData: MarketCurrencyData[];
      page: number;
    },
    Error
  >[],
) {
  const hashMap = new Map<string, HashMapBody>();

  results.forEach(result => {
    if (result.data) {
      hashMap.set(String(result.data.page), {
        updatedAt: result.dataUpdatedAt,
        refetch: result.refetch,
      });
    }
  });

  return {
    data: results.flatMap(result => result.data?.formattedData ?? []),
    isPending: results.some(result => result.isPending),
    isFetching: results.some(result => result.isFetching),
    isLoading: results.some(result => result.isLoading),
    isError: results.some(result => result.isError),
    cachedMetadataMap: hashMap,
  };
}
