import React, { forwardRef, useState, useMemo, useRef } from "react";
import { getCoreRowModel, useReactTable, getSortedRowModel, getFilteredRowModel } from "@tanstack/react-table";
import { useForkRef } from "../../hooks";
import cls from "classnames";
import { classes } from "./Table.tokens";
import { SELECT_COLUMN_ID } from "./utils";
import { HeadCell, Cell, EditableCell } from "./ui";
import { base, Table, Tr, Thead, StyledCheckbox, Tbody, ScrollableWrapper } from "./Table.styles";
export const tableRoot = (Root)=>/*#__PURE__*/ forwardRef(({ data, onChange, columns, view, size, borderVariant = 'all', enableSelection = false, selected: outerSelected, filtered: outerFiltered, sorted: outerSorted, maxHeight, stickyHeader = false, onCellUpdate, setRowProps, topContent, bottomContent, loadingSlot, onScroll, classNames, ...props }, ref)=>{
        const [innerSelected, innerSetSelected] = useState(outerSelected || {});
        const [innerFiltered, setInnerFiltered] = useState(outerFiltered || []);
        const [innerSorted, setInnerSorted] = useState(outerSorted || []);
        const selected = outerSelected || innerSelected;
        const filtered = outerFiltered || innerFiltered;
        const sorted = outerSorted || innerSorted;
        const handleRowSelection = (updaterOrValue)=>{
            if (!outerSelected) {
                innerSetSelected(updaterOrValue);
            }
            if (onChange) {
                onChange({
                    selected: typeof updaterOrValue === 'function' ? updaterOrValue(selected) : updaterOrValue,
                    filtered,
                    sorted
                });
            }
        };
        const handleSorting = (updaterOrValue)=>{
            if (!outerSorted) {
                setInnerSorted(updaterOrValue);
            }
            if (onChange) {
                onChange({
                    selected,
                    filtered,
                    sorted: typeof updaterOrValue === 'function' ? updaterOrValue(sorted) : updaterOrValue
                });
            }
        };
        const handleFiltering = (updaterOrValue)=>{
            if (!outerFiltered) {
                setInnerFiltered(updaterOrValue);
            }
            if (onChange) {
                onChange({
                    selected,
                    filtered: typeof updaterOrValue === 'function' ? updaterOrValue(filtered) : updaterOrValue,
                    sorted
                });
            }
        };
        const tableContainerRef = useRef(null);
        const rootRef = useForkRef(tableContainerRef, ref);
        const columnsData = useMemo(()=>[
                ...enableSelection ? [
                    {
                        id: SELECT_COLUMN_ID,
                        header: ({ table })=>/*#__PURE__*/ React.createElement(StyledCheckbox, {
                                checked: table.getIsSomeRowsSelected() || table.getIsAllRowsSelected(),
                                indeterminate: table.getIsSomeRowsSelected(),
                                onChange: table.getToggleAllRowsSelectedHandler(),
                                // eslint-disable-next-line no-underscore-dangle
                                appearance: props._checkboxAppearance ?? 'default'
                            }),
                        cell: ({ row })=>/*#__PURE__*/ React.createElement(StyledCheckbox, {
                                checked: row.getIsSelected(),
                                indeterminate: row.getIsSomeSelected(),
                                onChange: row.getToggleSelectedHandler(),
                                // eslint-disable-next-line no-underscore-dangle
                                appearance: props._checkboxAppearance ?? 'default'
                            }),
                        enableResizing: false
                    }
                ] : [],
                ...columns.map(({ id, label, filters, enableSorting = false, enableResizing = false, filterFn: outerFilterFn, width: columnSize, enableEditing = false, renderCell, setCellProps })=>({
                        header: label,
                        accessorKey: id,
                        size: columnSize,
                        enableSorting,
                        enableResizing,
                        filterFn: (row, columnId, filterArr)=>{
                            if (filterArr?.length !== 0 && outerFilterFn && filterArr && Array.isArray(filterArr)) {
                                return filterArr.some((filterValue)=>outerFilterFn(filterValue, row.getValue(columnId)));
                            }
                            return true;
                        },
                        meta: {
                            filters,
                            enableEditing,
                            renderCell,
                            setCellProps
                        }
                    }))
            ], [
            enableSelection,
            columns
        ]);
        const table = useReactTable({
            data,
            columns: columnsData,
            getRowId: (row)=>row.id,
            getCoreRowModel: getCoreRowModel(),
            getSortedRowModel: getSortedRowModel(),
            manualSorting: Boolean(outerSorted),
            manualFiltering: Boolean(outerFiltered),
            state: {
                rowSelection: selected,
                columnFilters: filtered,
                sorting: sorted
            },
            onSortingChange: handleSorting,
            getFilteredRowModel: getFilteredRowModel(),
            onColumnFiltersChange: handleFiltering,
            onRowSelectionChange: handleRowSelection,
            columnResizeMode: 'onChange',
            columnResizeDirection: 'ltr',
            manualPagination: true,
            meta: {
                updateData: (rowId, columnId, value)=>{
                    if (onCellUpdate) {
                        onCellUpdate(rowId, columnId, value);
                    }
                }
            }
        });
        return /*#__PURE__*/ React.createElement(Root, {
            ref: rootRef,
            view: view,
            size: size,
            className: cls(props.className, classNames?.root, classes.root),
            ...props
        }, topContent, /*#__PURE__*/ React.createElement(ScrollableWrapper, {
            className: classes.scrollableContainer,
            onScroll: onScroll,
            maxHeight: maxHeight
        }, /*#__PURE__*/ React.createElement(Table, {
            borderVariant: borderVariant,
            stickyHeader: stickyHeader,
            className: cls(classNames?.table, classes.table)
        }, /*#__PURE__*/ React.createElement(Thead, {
            view: view,
            borderVariant: borderVariant,
            stickyHeader: stickyHeader,
            className: cls(classNames?.header?.wrapper, classes.headerWrapper)
        }, table.getHeaderGroups().map((headerGroup)=>/*#__PURE__*/ React.createElement(Tr, {
                key: headerGroup.id,
                className: cls(classNames?.header?.row, classes.headerRow)
            }, headerGroup.headers.map((header)=>/*#__PURE__*/ React.createElement(HeadCell, {
                    key: header.index,
                    header: header,
                    size: size,
                    borderVariant: borderVariant,
                    outerFiltered: outerFiltered,
                    tableContainerRef: tableContainerRef,
                    className: cls(classNames?.header?.cell, classes.headerCell)
                }))))), /*#__PURE__*/ React.createElement(Tbody, {
            className: cls(classNames?.body?.wrapper, classes.bodyWrapper)
        }, table.getRowModel().rows.map((row)=>/*#__PURE__*/ React.createElement(Tr, {
                key: row.id,
                selected: row.getIsSelected(),
                className: cls(classNames?.body?.row, classes.bodyRow),
                ...setRowProps?.(row.original)
            }, row.getVisibleCells().map((cell)=>{
                const additionalProps = cell?.column?.columnDef?.meta?.setCellProps?.(cell.row.original, cell.id) || {};
                return cell?.column?.columnDef?.meta?.enableEditing ? /*#__PURE__*/ React.createElement(EditableCell, {
                    key: cell.id,
                    size: size,
                    cell: cell,
                    borderVariant: borderVariant,
                    table: table,
                    selected: row.getIsSelected(),
                    view: view,
                    additionalProps: additionalProps,
                    className: cls(classNames?.body?.cell, classes.bodyCell)
                }) : /*#__PURE__*/ React.createElement(Cell, {
                    key: cell.id,
                    cell: cell,
                    borderVariant: borderVariant,
                    selected: row.getIsSelected(),
                    view: view,
                    additionalProps: additionalProps,
                    className: cls(classNames?.body?.cell, classes.bodyCell)
                });
            }))))), loadingSlot), bottomContent);
    });
export const tableConfig = {
    name: 'Table',
    tag: 'div',
    layout: tableRoot,
    base,
    variations: {},
    defaults: {
        view: 'default',
        size: 'm'
    }
};
