import { createElement as _createElement } from "react";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { createColumnHelper, getCoreRowModel, getFilteredRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
import { Button } from "../button/button";
import { TextField } from "../textField/textField";
import { Select } from "../select/select";
import { ADPIcon, iconList } from "../adpIcon/adpIcon";
import { Pagination } from "../pagination/pagination";
import { Checkbox } from "../checkbox/checkbox";
import { cn, debounce, findParentAttribute } from "@utils";
import { dataTableContainerVariants, dataTableFiltersVariants, dataTableFilterSearchVariants, dataTableFilterSelectVariants, dataTableRecordsInfoVariants, dataTableContainerInnerVariants, dataTablePaginationVariants } from "./dataTableVariants";
import { PageSizeModal } from "./pageSizeModal";
import { DataTableColumnSettings } from "./DataTableColumnSettings";
import { AdvancedFilters } from "./advancedFilters";
import SelectedFilterList from "./selectedFilterList";
import { Table } from "./table";
// Utility function to derive configured columns
const deriveConfiguredColumns = (rawColumns, selectable, columnHelper) => {
    var _a, _b, _c;
    const derivedColumns = [
        ...(selectable
            ? [
                columnHelper.accessor("select", {
                    id: "select",
                    header: ({ table }) => (_jsx(Checkbox, { checked: table.getIsAllRowsSelected(), "data-indeterminate": table.getIsSomeRowsSelected().toString(), onChange: table.getToggleAllPageRowsSelectedHandler() })),
                    cell: ({ row }) => (_jsx(Checkbox, { checked: row.getIsSelected(), disabled: !row.getCanSelect(), "data-indeterminate": row.getIsSomeSelected().toString(), onChange: row.getToggleSelectedHandler() })),
                    enableResizing: false,
                    enableSorting: false,
                    size: 56
                })
            ]
            : []),
        ...((_c = (_b = (_a = rawColumns === null || rawColumns === void 0 ? void 0 : rawColumns.sort((a, b) => { var _a, _b; return Number((_a = b === null || b === void 0 ? void 0 : b.fixed) !== null && _a !== void 0 ? _a : false) - Number((_b = a === null || a === void 0 ? void 0 : a.fixed) !== null && _b !== void 0 ? _b : false); })) === null || _a === void 0 ? void 0 : _a.filter(el => (el === null || el === void 0 ? void 0 : el.selected) === undefined || (el === null || el === void 0 ? void 0 : el.selected) !== false)) === null || _b === void 0 ? void 0 : _b.map((column) => {
            const { cell, key, header, enableResizing, enableSorting, sortingFn, size } = column;
            return columnHelper.accessor(key, Object.assign(Object.assign({ header: header, cell: (info) => {
                    return _jsx(_Fragment, { children: typeof cell === "function" ? cell(info) : info.getValue() });
                }, enableResizing: enableResizing !== null && enableResizing !== void 0 ? enableResizing : true, enableSorting: enableSorting !== null && enableSorting !== void 0 ? enableSorting : true }, (sortingFn ? { sortingFn } : {})), { size: size ? size : 400 }));
        })) !== null && _c !== void 0 ? _c : [])
    ];
    return derivedColumns;
};
const DEBOUNCE_TIME = 500;
const HEIGHT = "500px";
// Default page size options (maintained for backward compatibility but currently unused)
const PAGE_SIZE_OPTIONS = [25, 50, 100, 200, 500, 1000];
/**
 * DataTable is a powerful component that displays tabular data with advanced features
 * like filtering, sorting, pagination, and row selection.
 */
export const DataTable = ({ advancedFilters, basicFilters, className, columns, data = [], filters, loading = false, paginationProps, resizable = false, selectable = false, 
/** pin first column on left */
pinnedFirstColumn = true, 
/** enable row virtualization */
rowVirtualization = true, 
/** enable column virtualization */
columnVirtualization = true, sorting, height = HEIGHT, customCTAs, searchProps, pageSizeOptions = PAGE_SIZE_OPTIONS, setFilters, setSorting, onRefresh, onRowSelection, setColumns }) => {
    var _a, _b, _c, _d;
    const columnHelper = createColumnHelper();
    const [configuredColumns, setConfiguredColumns] = useState(deriveConfiguredColumns(columns, selectable, columnHelper));
    const [globalFilter, setGlobalFilter] = useState("");
    const [rowSelection, setRowSelection] = useState({});
    const [selectedFilters, setSelectedFilters] = useState(filters || {});
    const [columnPinning, setColumnPinning] = useState({
        left: pinnedFirstColumn ? ["select", (_b = (_a = configuredColumns === null || configuredColumns === void 0 ? void 0 : configuredColumns[1]) === null || _a === void 0 ? void 0 : _a.accessorKey) !== null && _b !== void 0 ? _b : ""] : []
    });
    const { totalRecords, offset, pageSize, onPageChange, onPageSizeChange } = paginationProps !== null && paginationProps !== void 0 ? paginationProps : {};
    const [showRecordsChangeModal, setShowRecordsChangeModal] = useState(false);
    const tableContainerRef = useRef(null);
    const [isRtl, setIsRtl] = useState(false);
    const [showSettingsDropdown, setShowSettingsDropdown] = useState(false);
    const totalPages = totalRecords && pageSize && Math.ceil(totalRecords / pageSize);
    const table = useReactTable({
        data,
        columns: configuredColumns,
        state: {
            rowSelection,
            globalFilter,
            sorting,
            columnPinning
        },
        globalFilterFn: "includesString",
        columnResizeMode: "onChange",
        columnResizeDirection: "ltr",
        enableRowSelection: selectable,
        getCoreRowModel: getCoreRowModel(),
        getFilteredRowModel: (_c = getFilteredRowModel()) !== null && _c !== void 0 ? _c : undefined,
        onRowSelectionChange: setRowSelection !== null && setRowSelection !== void 0 ? setRowSelection : undefined,
        onGlobalFilterChange: setGlobalFilter !== null && setGlobalFilter !== void 0 ? setGlobalFilter : undefined,
        onSortingChange: setSorting !== null && setSorting !== void 0 ? setSorting : undefined,
        getSortedRowModel: sorting ? getSortedRowModel() : undefined,
        onColumnPinningChange: setColumnPinning !== null && setColumnPinning !== void 0 ? setColumnPinning : undefined
    });
    // For handling basic filter
    const handleBasicFilterChange = (e, id) => {
        var _a, _b;
        setSelectedFilters((prev) => (Object.assign(Object.assign({}, prev), { [id]: e })));
        (_b = (_a = basicFilters === null || basicFilters === void 0 ? void 0 : basicFilters.find((el) => el.id === id)) === null || _a === void 0 ? void 0 : _a.onChange) === null || _b === void 0 ? void 0 : _b.call(_a);
    };
    // Clear advanced filters -
    const handleClearFilter = () => {
        const newSelectedFilters = Object.keys(selectedFilters).reduce((acc, key) => {
            if (basicFilters === null || basicFilters === void 0 ? void 0 : basicFilters.some((filter) => filter.id === key)) {
                acc[key] = selectedFilters[key];
            }
            return acc;
        }, {});
        setSelectedFilters(newSelectedFilters);
        advancedFilters === null || advancedFilters === void 0 ? void 0 : advancedFilters.forEach((filter) => {
            if (filter === null || filter === void 0 ? void 0 : filter.setSelectedValue) {
                filter === null || filter === void 0 ? void 0 : filter.setSelectedValue(null);
            }
        });
    };
    // Remove filter from selected filter list -
    const handleRemoveFilter = (key, index) => {
        setSelectedFilters((prevFilters) => {
            const updatedFilters = Object.assign({}, prevFilters);
            const value = updatedFilters[key];
            if (Array.isArray(value) && typeof index === "number") {
                updatedFilters[key] = value.filter((_, i) => i !== index);
                if (updatedFilters[key].length === 0) {
                    delete updatedFilters[key];
                }
            }
            else {
                delete updatedFilters[key];
            }
            return updatedFilters;
        });
        advancedFilters === null || advancedFilters === void 0 ? void 0 : advancedFilters.forEach((filter) => {
            if ((filter === null || filter === void 0 ? void 0 : filter.id) === key && (filter === null || filter === void 0 ? void 0 : filter.setSelectedValue)) {
                if (Array.isArray(selectedFilters[key]) && typeof index === "number") {
                    const arr = [...selectedFilters[key]];
                    arr.splice(index, 1);
                    filter.setSelectedValue(arr.length ? arr : null);
                }
                else {
                    filter.setSelectedValue(null);
                }
            }
        });
    };
    const handleClearAllSelectedFilters = () => {
        setSelectedFilters({});
        advancedFilters === null || advancedFilters === void 0 ? void 0 : advancedFilters.forEach((filter) => {
            if (filter === null || filter === void 0 ? void 0 : filter.setSelectedValue) {
                filter === null || filter === void 0 ? void 0 : filter.setSelectedValue(null);
            }
        });
    };
    const toggleRecordsModal = () => {
        setShowRecordsChangeModal(!showRecordsChangeModal);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
    const onSearchInput = useCallback(debounce((value) => {
        var _a;
        (_a = searchProps === null || searchProps === void 0 ? void 0 : searchProps.onSearch) === null || _a === void 0 ? void 0 : _a.call(searchProps, value);
    }, (_d = searchProps === null || searchProps === void 0 ? void 0 : searchProps.debounceTime) !== null && _d !== void 0 ? _d : DEBOUNCE_TIME), []);
    const onSearchTextChange = (e) => {
        if ((searchProps === null || searchProps === void 0 ? void 0 : searchProps.onChange) && typeof (searchProps === null || searchProps === void 0 ? void 0 : searchProps.onChange) === "function") {
            searchProps === null || searchProps === void 0 ? void 0 : searchProps.onChange(e);
        }
        if (typeof (searchProps === null || searchProps === void 0 ? void 0 : searchProps.onSearch) === "undefined") {
            setGlobalFilter(e.target.value);
        }
        else {
            onSearchInput(e.target.value);
        }
    };
    // Filter Bar of the Data Table
    const FilterBar = () => {
        var _a;
        const { value = "", placeholder = "Search in this page", hidden } = searchProps || {};
        return (_jsxs("div", { className: cn(dataTableFiltersVariants()), children: [!hidden && (_jsx(TextField, { placeholder: placeholder, prefixIcon: iconList.search, className: cn(dataTableFilterSearchVariants()), onChange: onSearchTextChange, value: value ? value : globalFilter, suffixIcon: globalFilter || value ? (_jsx(ADPIcon, { className: "cursor-pointer", icon: iconList.cross, onClick: () => {
                            if (searchProps === null || searchProps === void 0 ? void 0 : searchProps.onSearch) {
                                searchProps.onSearch("");
                            }
                            else {
                                setGlobalFilter("");
                            }
                        } })) : undefined })), (_a = basicFilters === null || basicFilters === void 0 ? void 0 : basicFilters.slice(0, 3)) === null || _a === void 0 ? void 0 : _a.map((props) => {
                    var _a;
                    return (_createElement(Select, Object.assign({}, props, { options: props === null || props === void 0 ? void 0 : props.options, "data-testid": `table-filter-${props.id}`, key: props.id, className: cn(dataTableFilterSelectVariants()), onChange: (e) => { var _a; return handleBasicFilterChange(e, (_a = props.id) !== null && _a !== void 0 ? _a : ""); }, value: selectedFilters[(_a = props.id) !== null && _a !== void 0 ? _a : ""] || null, prefixIcon: props.icon ? _jsx(ADPIcon, { className: "text-gray-800", icon: props.icon }) : undefined, placeholder: _jsx("div", { className: "flex gap-2 items-center", children: _jsx("span", { className: "text-secondary-500 dark:text-secondary-400 font-medium text-xs", children: (props === null || props === void 0 ? void 0 : props.placeholder) || (props === null || props === void 0 ? void 0 : props.title) }) }) })));
                }), advancedFilters && advancedFilters.length > 0 && (_jsx(AdvancedFilters, { advancedFilters: advancedFilters, basicFilters: basicFilters, selectedFilters: selectedFilters, setSelectedFilters: setSelectedFilters, handleClearFilter: handleClearFilter })), _jsxs("div", { className: "flex items-center gap-4 ms-auto", children: [typeof onRefresh === "function" && (_jsx(Button, { prefixIcon: iconList.reload, size: "xs", variant: "outline", className: "border-primary-500", onClick: onRefresh })), columns && (_jsxs("div", { className: "relative", children: [_jsx(Button, { prefixIcon: iconList.settings, size: "xs", variant: "outline", className: "border-primary-500", onClick: () => setShowSettingsDropdown(!showSettingsDropdown) }), _jsx(DataTableColumnSettings, { columns: columns, setColumns: setColumns, isOpen: showSettingsDropdown, onClose: () => setShowSettingsDropdown(false) })] }))] }), customCTAs] }));
    };
    useEffect(() => {
        setConfiguredColumns(deriveConfiguredColumns(columns, selectable, columnHelper));
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [columns]);
    // Return the selected rows
    useEffect(() => {
        if (rowSelection) {
            onRowSelection === null || onRowSelection === void 0 ? void 0 : onRowSelection(rowSelection);
        }
    }, [onRowSelection, rowSelection]);
    useEffect(() => {
        setFilters === null || setFilters === void 0 ? void 0 : setFilters(selectedFilters);
    }, [selectedFilters, setFilters]);
    useEffect(() => {
        var _a, _b;
        setColumnPinning({
            left: pinnedFirstColumn ? ["select", (_b = (_a = configuredColumns === null || configuredColumns === void 0 ? void 0 : configuredColumns[selectable ? 1 : 0]) === null || _a === void 0 ? void 0 : _a.accessorKey) !== null && _b !== void 0 ? _b : ""] : []
        });
    }, [configuredColumns, selectable, pinnedFirstColumn]);
    useEffect(() => {
        const tableContainer = tableContainerRef.current;
        if (tableContainer) {
            const dir = findParentAttribute(tableContainer, "dir");
            setIsRtl(dir === "rtl");
        }
    }, [tableContainerRef]);
    return (_jsxs("div", { "data-testid": "table", className: cn(dataTableContainerVariants(), className), ref: tableContainerRef, children: [FilterBar(), _jsx(SelectedFilterList, { advancedFilters: advancedFilters !== null && advancedFilters !== void 0 ? advancedFilters : [], basicFilters: basicFilters !== null && basicFilters !== void 0 ? basicFilters : [], selectedFilters: selectedFilters, handleRemoveFilter: handleRemoveFilter, handleClearAllSelectedFilters: handleClearAllSelectedFilters }), _jsx("div", { className: cn(dataTableRecordsInfoVariants()), children: totalRecords && offset && pageSize && !loading ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "text-secondary-400 dark:text-secondary-200", children: ["Showing ", offset, " - ", Math.min(offset - 1 + pageSize, totalRecords), " of ", totalRecords, " results.", " "] }), _jsx(Button, { size: "sm", variant: "text", onClick: toggleRecordsModal, className: "inline", children: "See more" })] })) : _jsx(_Fragment, {}) }), _jsx("div", { className: cn(dataTableContainerInnerVariants()), style: { height }, children: _jsx(Table, { table: table, columnVirtualization: columnVirtualization, rowVirtualization: rowVirtualization, selectable: selectable, loading: loading, resizable: resizable, height: height !== null && height !== void 0 ? height : HEIGHT, isRtl: isRtl }) }), Boolean(totalPages) && _jsx("div", { className: cn(dataTablePaginationVariants()), children: _jsx(Pagination, { layout: "detailed", variant: "outline", totalPages: totalPages, onPageChange: onPageChange, activePageNo: offset && Math.ceil(offset / (pageSize !== null && pageSize !== void 0 ? pageSize : 25)) }) }), _jsx(PageSizeModal, { show: showRecordsChangeModal, toggleVisibility: toggleRecordsModal, pageSize: pageSize || 25, pageSizeOptions: pageSizeOptions, onPageSizeChange: onPageSizeChange, onPageChange: onPageChange })] }));
};
//# sourceMappingURL=dataTable.js.map