import {
  TData,
  PaginatedResponse,
  PaginatedRequest,
  DataTableTransformer,
} from "../types";
import { PaginationState, OnChangeFn } from "@tanstack/react-table";
import React, { useMemo, useState } from "react";
import { useQuery, UseQueryResult } from "@tanstack/react-query";

export interface UseDataTableProps<T extends TData> {
  /**
   * The query function to call inside the paginated useQuery function
   * @param page The page number to query
   * @returns The paginated query data
   */
  queryFn: (props: PaginatedRequest) => Promise<PaginatedResponse<T>>;
  /**
   * The query key to use inside the paginated useQuery function
   */
  queryKey: string;
  /**
   * An optional transform function to apply to the data used in the table
   */
  transformer?: DataTableTransformer<T>;
}

export interface UseDataTableReturn<T extends TData> {
  /**
   * The paginated data including the currently selected page index and page size
   */
  pagination: PaginationState;
  /**
   * The pagination change handler to update the page index and page size
   */
  onPaginationChange: OnChangeFn<PaginationState>;
  /**
   * The query response from the useQuery hook, including pagination handlers
   */
  queryResponse: UseQueryResult<PaginatedResponse<T>>;
  /**
   * An optional transform function to apply to the data used in the table
   */
  transformer?: DataTableTransformer<T>;
}

export const useDataTable = <T extends TData>({
  queryFn,
  queryKey,
  transformer,
}: UseDataTableProps<T>): UseDataTableReturn<T> => {
  const [{ pageIndex, pageSize }, onPaginationChange] =
    useState<PaginationState>({
      pageIndex: 0,
      pageSize: 10,
    });
  const pagination = useMemo<PaginationState>(
    () => ({ pageIndex, pageSize }),
    [pageIndex, pageSize]
  );
  const queryResponse = useQuery<PaginatedResponse<T>>({
    queryFn: () => queryFn({ pageIndex, pageSize }),
    queryKey: [queryKey, pageIndex, pageSize],
  });

  return {
    pagination,
    onPaginationChange,
    queryResponse,
    transformer,
  };
};
