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

import { getDataTableSelectionColumn } from "@/components";
import React, { useCallback, useMemo, useState } from "react";
import { useSearchParams } from "react-router-dom";
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;

  /**
   * 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;
}

export function useDataTable<TData, TValue>({
  data,
  columns,
  pageCount,
  enableSorting = false,
  enableHiding = false,
  enableRowSelection = false,
  onPaginationChange,
  filterFields = [],
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  enableAdvancedFilter = false,
}: UseDataTableProps<TData, TValue>) {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const [searchParams, setSearchParams] = useSearchParams();

  const { pagination, setPagination } = useDataTableContext();
  console.log("pagination TABLA =>", pagination);

  const [sorting, setSorting] = useState<SortingState>([]);

  // Memoize computation of searchableColumns and filterableColumns
  const { searchableColumns, filterableColumns } = useMemo(() => {
    return {
      searchableColumns: filterFields.filter((field) => !field.options),
      filterableColumns: filterFields.filter((field) => field.options),
    };
  }, [filterFields]);

  // Create query string
  /*const createQueryString = useCallback(
    (params: Record<string, string | number | null>) => {
      const newSearchParams = new URLSearchParams(searchParams?.toString());

      for (const [key, value] of Object.entries(params)) {
        if (value === null) {
          newSearchParams.delete(key);
        } else {
          newSearchParams.set(key, String(value));
        }
      }

      return newSearchParams.toString();
    },
    [searchParams]
  );*/

  // Initial column filters
  const initialColumnFilters: ColumnFiltersState = useMemo(() => {
    return Array.from(searchParams.entries()).reduce<ColumnFiltersState>(
      (filters, [key, value]) => {
        const filterableColumn = filterableColumns.find((column) => column.value === key);
        const searchableColumn = searchableColumns.find((column) => column.value === key);

        if (filterableColumn) {
          filters.push({
            id: key,
            value: value.split("."),
          });
        } else if (searchableColumn) {
          filters.push({
            id: key,
            value: [value],
          });
        }

        return filters;
      },
      []
    );
  }, [filterableColumns, searchableColumns, searchParams]);

  // Table states
  const [rowSelection, setRowSelection] = React.useState({});

  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});

  const [columnFilters, setColumnFilters] =
    React.useState<ColumnFiltersState>(initialColumnFilters);

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

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

  // Handle server-side filtering
  /*const debouncedSearchableColumnFilters = JSON.parse(
    useDebounce(
      JSON.stringify(
        columnFilters.filter((filter) => {
          return searchableColumns.find((column) => column.value === filter.id);
        })
      ),
      500
    )
  ) as ColumnFiltersState;*/

  /*const filterableColumnFilters = columnFilters.filter((filter) => {
    return filterableColumns.find((column) => column.value === filter.id);
  });

  const [mounted, setMounted] = useState(false);*/

  /*useEffect(() => {
    // Opt out when advanced filter is enabled, because it contains additional params
    if (enableAdvancedFilter) return;

    // Prevent resetting the page on initial render
    if (!mounted) {
      setMounted(true);
      return;
    }

    // Initialize new params
    const newParamsObject = {
      page: 1,
    };

    // Handle debounced searchable column filters
    for (const column of debouncedSearchableColumnFilters) {
      if (typeof column.value === "string") {
        Object.assign(newParamsObject, {
          [column.id]: typeof column.value === "string" ? column.value : null,
        });
      }
    }

    // Handle filterable column filters
    for (const column of filterableColumnFilters) {
      if (typeof column.value === "object" && Array.isArray(column.value)) {
        Object.assign(newParamsObject, { [column.id]: column.value.join(".") });
      }
    }

    // Remove deleted values
    for (const key of searchParams.keys()) {
      if (
        (searchableColumns.find((column) => column.value === key) &&
          !debouncedSearchableColumnFilters.find(
            (column) => column.id === key
          )) ||
        (filterableColumns.find((column) => column.value === key) &&
          !filterableColumnFilters.find((column) => column.id === key))
      ) {
        Object.assign(newParamsObject, { [key]: null });
      }
    }

    // After cumulating all the changes, push new params
    navigate(`${location.pathname}?${createQueryString(newParamsObject)}`);

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    // eslint-disable-next-line react-hooks/exhaustive-deps
    //JSON.stringify(debouncedSearchableColumnFilters),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    JSON.stringify(filterableColumnFilters),
  ]);*/

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

  const table = useReactTable({
    columns: getTableColumns(),
    data,
    getCoreRowModel: getCoreRowModel(),
    //getPaginationRowModel: getPaginationRowModel(),

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

    enableRowSelection,
    onRowSelectionChange: setRowSelection,

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

    enableHiding,
    onColumnVisibilityChange: setColumnVisibility,

    manualPagination: true,
    pageCount: pageCount ?? -1,
    onPaginationChange: paginationUpdater,

    getFilteredRowModel: getFilteredRowModel(),

    manualFiltering: true,
    onColumnFiltersChange: setColumnFilters,

    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
  });

  return { table };
}
