import { type InfiniteData, infiniteQueryOptions, type QueryKey } from '@tanstack/react-query';

import { store } from '@/store';

import {
  PaginatedResponseArray,
  type PaginatedResponseQueryResult,
} from './make-paginated-response-query';

import type { PaginatedResponse, PlApiClient } from 'pl-api';

const makePaginatedResponseQueryOptions =
  <
    T1 extends Array<any>,
    T2,
    IsArray extends boolean = true,
    T3 = PaginatedResponseQueryResult<T2, IsArray>,
  >(
    queryKey: QueryKey | ((...params: T1) => QueryKey),
    queryFn: (client: PlApiClient, params: T1) => Promise<PaginatedResponse<T2, IsArray>>,
    select?: (data: InfiniteData<PaginatedResponse<T2, IsArray>>) => T3,
  ) =>
  (...params: T1) =>
    infiniteQueryOptions({
      queryKey: typeof queryKey === 'object' ? queryKey : queryKey(...params),
      queryFn: ({ pageParam }) =>
        pageParam.next?.() ?? queryFn(store.getState().auth.client, params),
      initialPageParam: {
        previous: null,
        next: null,
        items: [] as unknown as PaginatedResponse<T2, IsArray>['items'],
        partial: false,
      } as Awaited<ReturnType<typeof queryFn>>,
      getNextPageParam: (page) => (page.next ? page : undefined),
      select:
        select ??
        ((data) => {
          const lastPage = data.pages.at(-1);

          if (!lastPage) {
            return new PaginatedResponseArray() as T3;
          }

          if (Array.isArray(lastPage.items)) {
            const items = new PaginatedResponseArray(
              ...data.pages.flatMap((page) =>
                Array.isArray(page.items) ? page.items : [page.items],
              ),
            );

            items.total = lastPage.total;
            items.partial = lastPage.partial;

            return items as T3;
          }

          return lastPage.items as T3;
        }),
    });

export { makePaginatedResponseQueryOptions };
