import {
  InitialTableState,
  OnChangeFn,
  PaginationState,
  getCoreRowModel,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getSortedRowModel,
  useReactTable,
  type ColumnDef,
  type SortingState,
  type VisibilityState,
} from "@tanstack/react-table";

import { getDataTableSelectionColumn } from "@/components";
import React, { useCallback } from "react";
import { DataTableFilterField } from "./types";
import { useDataTableContext } from "./useDataTableContext";

//import { useDebounce } from "@/hooks/use-debounce";

interface UseDataTableProps<TData, TValue> {
  /**
   * The data for the table.
   * @default []
   * @type TData[]
   */
  data: TData[];

  /**
   * The columns of the table.
   * @default []
   * @type ColumnDef<TData, TValue>[]
   */
  columns: ColumnDef<TData, TValue>[];

  /**
   * The number of pages in the table.
   * @type number
   */
  pageCount: number;

  /**
   * Enable sorting columns.
   * @default false
   * @type boolean
   */
  enableSorting?: boolean;

  /**
   * Enable hiding columns.
   * @default false
   * @type boolean
   */
  enableHiding?: boolean;

  /**
   * Enable selection rows.
   * @default false
   * @type boolean
   */
  enableRowSelection?: boolean;

  /**
   * The default number of rows per page.
   * @default 10
   * @type number | undefined
   * @example 20
   */
  defaultPerPage?: number;

  /**
   * The default sort order.
   * @default undefined
   * @type `${Extract<keyof TData, string | number>}.${"asc" | "desc"}` | undefined
   * @example "createdAt.desc"
   */
  defaultSort?: `${Extract<keyof TData, string | number>}.${"asc" | "desc"}`;

  /**
   * Defines filter fields for the table. Supports both dynamic faceted filters and search filters.
   * - Faceted filters are rendered when `options` are provided for a filter field.
   * - Otherwise, search filters are rendered.
   *
   * The indie filter field `value` represents the corresponding column name in the database table.
   * @default []
   * @type { label: string, value: keyof TData, placeholder?: string, options?: { label: string, value: string, icon?: React.ComponentType<{ className?: string }> }[] }[]
   * @example
   * ```ts
   * // Render a search filter
   * const filterFields = [
   *   { label: "Title", value: "title", placeholder: "Search titles" }
   * ];
   * // Render a faceted filter
   * const filterFields = [
   *   {
   *     label: "Status",
   *     value: "status",
   *     options: [
   *       { label: "Todo", value: "todo" },
   *       { label: "In Progress", value: "in-progress" },
   *       { label: "Done", value: "done" },
   *       { label: "Canceled", value: "canceled" }
   *     ]
   *   }
   * ];
   * ```
   */
  filterFields?: DataTableFilterField<TData>[];

  /**
   * Enable notion like column filters.
   * Advanced filters and column filters cannot be used at the same time.
   * @default false
   * @type boolean
   */
  enableAdvancedFilter?: boolean;

  initialState?: InitialTableState;

  onPaginationChange?: OnChangeFn<PaginationState>;
}

export function useDataTable<TData, TValue>({
  data,
  columns,
  pageCount,
  enableSorting = false,
  enableHiding = false,
  enableRowSelection = false,
  initialState,
  onPaginationChange,
}: UseDataTableProps<TData, TValue>) {
  const { pagination, setPagination, sorting } = useDataTableContext();

  // Table states
  const [rowSelection, setRowSelection] = React.useState({});
  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>(
    initialState?.columnVisibility || {}
  );

  const paginationUpdater: OnChangeFn<PaginationState> = (updater) => {
    if (typeof updater === "function") {
      const newPagination = updater(pagination);
      setPagination(newPagination);
    }
    if (onPaginationChange) {
      onPaginationChange(updater);
    }
  };

  const sortingUpdater: OnChangeFn<SortingState> = (updater) => {
    if (typeof updater === "function") {
      //const newSorting = updater(sorting);
      //console.log(newSorting);
      //setSorting(newSorting);
    }
  };

  const getTableColumns = useCallback(() => {
    const _columns = columns;
    if (enableRowSelection) {
      _columns.unshift(getDataTableSelectionColumn());
    }
    return _columns;
  }, [columns, enableRowSelection]);

  const table = useReactTable({
    data,
    columns: getTableColumns(),
    //autoResetPageIndex: true,
    pageCount: pageCount ?? -1,
    getCoreRowModel: getCoreRowModel(),

    initialState,

    state: {
      pagination,
      sorting,
      columnVisibility,
      rowSelection,
    },

    enableRowSelection,
    onRowSelectionChange: setRowSelection,

    manualSorting: true,
    enableSorting,
    getSortedRowModel: getSortedRowModel(),
    onSortingChange: sortingUpdater,

    enableHiding,
    onColumnVisibilityChange: setColumnVisibility,

    manualPagination: true,
    onPaginationChange: paginationUpdater,

    manualFiltering: true,
    getFilteredRowModel: getFilteredRowModel(),

    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),

    debugTable: false,
    debugHeaders: false,
    debugColumns: false,

    defaultColumn: {
      minSize: 0, //starting column size
      size: Number.MAX_SAFE_INTEGER, //enforced during column resizing
      maxSize: Number.MAX_SAFE_INTEGER, //enforced during column resizing
    },
  });

  return { table };
}
