import DataTableFilterDataStructure from "@/core/utils/DataTableFilterDataStructure";
import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
import isArrayEmpty from "@/core/utils/isArrayEmpty";
import useDataTable from "@/lib/hooks/useDataTable";
import useRequest from "@/lib/hooks/useRequest";
import { useMaterialReactTable } from "material-react-table";
import { useCallback, useEffect, useReducer, useState } from "react";
import useSWR from "swr";
import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable";
import DataTable_Paper from "./table/Paper";

const rowSelectionReducer = (state, action) => {
  switch (action.type) {
    case "TOGGLE_ROW":
      return { [action.payload]: true };
    case "RESET":
      return {};
    default:
      return state;
  }
};

const DataTable_Main = (props) => {
  const request = useRequest();
  const [rowSelection, dispatchRowSelection] = useReducer(
    rowSelectionReducer,
    {},
  );
  const { filterData, sortData, setSortData, hideData } = useDataTable();
  const {
    need_filter,
    table_url,
    user_id,
    page_name,
    table_name,
    columns,
    initialStateProps,
    TableToolbar,
    table_title,
    RowActions,
    specific_data,
    specialFilter,
  } = props;
  const flatColumns = flattenArrayOfObjects(columns, "columns");
  const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
  const [totalRowCount, setTotalRowCount] = useState(0);
  const flattenHideData = flattenObjectOfObjects(hideData);
  const onSortingChange = (event) => {
    setSortData(event);
  };

  const fetchUrl = useCallback(() => {
    const params = new URLSearchParams();
    params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
    params.set("size", pagination.pageSize);
    if (specialFilter) {
      const filteredSpecialFilterData = Object.values(specialFilter).filter(
        (filter) => !isArrayEmpty(filter.value),
      );
      params.set("filters", JSON.stringify(filteredSpecialFilterData || []));
    } else {
      const filteredFilterData = DataTableFilterDataStructure(
        filterData,
        isArrayEmpty,
      );
      params.set(
        "filters",
        JSON.stringify(
          filteredFilterData.length === 0 ? [] : filteredFilterData,
        ),
      );
    }
    params.set(
      "sorting",
      JSON.stringify(
        Object.values(sortData).map(({ id, ...rest }) => ({
          ...rest,
          id: id.replace(/__/g, "."),
        })),
      ),
    );
    return `${table_url}?${params}`;
  }, [table_url, filterData, pagination, sortData, specialFilter]);

  const fetcher = async (url) => {
    try {
      const response = await request(url);
      setTotalRowCount(response.data?.meta?.totalRowCount);
      if (specific_data) {
        return specific_data(response.data);
      } else {
        return response.data?.data;
      }
    } catch (error) {
      throw error;
    }
  };

  const { data, isValidating, mutate } = useSWR(
    props.data ? "" : fetchUrl(),
    fetcher,
    {
      revalidateIfStale: true,
      revalidateOnFocus: false,
      revalidateOnReconnect: true,
      keepPreviousData: true,
    },
  );

  useEffect(() => {
    if (!isValidating) return;
    dispatchRowSelection({ type: "RESET" });
  }, [isValidating]);

  const table = useMaterialReactTable({
    localization: FA_DATATABLE_LOCALIZATION,
    columns,
    data: data ?? [],
    muiTableBodyRowProps: ({ row }) => ({
      onClick: () =>
        dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }),
      selected: !!rowSelection[row.id],
    }),
    initialState: {
      density: "compact",
      columnVisibility: flattenHideData,
      sorting: sortData,
      ...initialStateProps,
    },
    state: {
      showProgressBars: isValidating || props.loading,
      columnVisibility: flattenHideData,
      sorting: sortData,
      pagination,
      rowSelection,
    },
    muiTableHeadProps: {
      sx: {
        borderTop: "1px solid #e1e1e1",
        borderBottom: "2px solid #e1e1e1",
      },
    },
    muiTableHeadCellProps: {
      sx: {
        color: "primary.main",
        borderLeft: "1px solid #e1e1e1",
        "&:first-of-type": {
          borderLeft: "unset",
        },
      },
    },
    muiTableBodyCellProps: {
      sx: {
        borderLeft: "1px solid #e1e1e1",
        "&:first-of-type": {
          borderLeft: "unset",
        },
      },
    },
    manualFiltering: true,
    manualPagination: true,
    manualSorting: true,
    onPaginationChange: setPagination,
    onSortingChange: onSortingChange,
    rowCount: totalRowCount,
    renderTopToolbarCustomActions: ({ table }) => (
      <>
        {TableToolbar && (
          <TableToolbar
            table={table}
            mutate={mutate}
            filterData={specialFilter || filterData}
          />
        )}
      </>
    ),
    renderRowActions: ({ row }) => <RowActions row={row} mutate={mutate} />,
    ...props,
  });

  return (
    <DataTable_Paper
      table={table}
      table_title={table_title}
      need_filter={need_filter}
      mutate={mutate}
      table_url={table_url}
      columns={flatColumns}
      user_id={user_id}
      page_name={page_name}
      table_name={table_name}
      special_data={props.data}
      special_filter={specialFilter}
      setFilterData={props.setFilterData}
    />
  );
};
export default DataTable_Main;
