'use client';
import clsx from 'clsx';
import { useEffect, useState, } from 'react';
import { Each, Show } from '../../00-base';
import { Checkbox, Tooltip } from '../../01-atoms';
import { Dropdown } from '../Dropdown/Dropdown';
import { TableEmpty } from './TableEmpty';
import { TableSkeleton } from './TableSkeleton';
import { getIndex, renderTableCellContent } from './utils';
/**
 * Table component for rendering data
 *
 * @example
 * <Table
 *   headers={[
 *     { key: 'id', title: 'ID' },
 *     { key: 'name', title: 'Name' },
 *   ]}
 *   id="id"
 *   data={[
 *     { id: 1, name: 'John' },
 *     { id: 2, name: 'Jane' },
 *   ]}
 *   selectable={true}
 *   multiple={true}
 *   currentSelection={{}}
 *   setCurrentSelection={(selection) => console.log(selection)}
 *   action={(item) => console.log(item)}
 *   actions={(item) => [
 *     { children: 'Edit', onClick: () => console.log('Edit', item) },
 *   ]}
 *   loading={false}
 *   numberOfRows={10}
 * />
 *
 * @param {Object} props - The properties for the Table component.
 * @param {Array<{ key: string, title: string | ReactNode }>} props.headers - The headers of the table.
 * @param {string} props.id - The unique identifier for each row.
 * @param {Array<TableItem>} props.data - The data to be displayed in the table.
 * @param {boolean} [props.selectable=false] - Whether the table rows are selectable.
 * @param {boolean} [props.multiple=true] - Whether multiple rows can be selected.
 * @param {TableItemSelection | TableItem} [props.currentSelection={}] - The current selection of rows.
 * @param {Function} [props.setCurrentSelection] - The function to update the current selection.
 * @param {Function} [props.action] - The function to be called when a row is clicked.
 * @param {Function} [props.actions] - The function to generate actions for each row.
 * @param {Object} [props.tableProps] - Additional properties for the table element.
 * @param {boolean} [props.loading=false] - Whether the table is in a loading state.
 * @param {number} [props.numberOfRows=10] - The number of rows to display when loading.
 * @param {Object} restProps - Additional properties for the container div.
 *
 * @returns {ReactNode} The rendered Table component.
 */
export function Table({ headers, id, data, action, actions, selectable = false, multiple = true, currentSelection, setCurrentSelection, tableProps, loading = false, numberOfRows = 10, footer, ...restProps }) {
    const [selected, setSelected] = useState(multiple ? currentSelection ?? {} : currentSelection);
    const [selectAll, setSelectAll] = useState(false);
    const buttonClass = clsx('action disabled:text-gray-3 rounded-sm p-2 text-base transition-colors not-disabled:hover:bg-black not-disabled:hover:text-white', restProps.className);
    const handlerClick = (event, item) => {
        const target = event.target;
        const parent = target.closest('.action');
        if (target.tagName === 'LABEL' || target.tagName === 'INPUT' || parent) {
            return;
        }
        if (!multiple && selectable) {
            return handlerSelect(item);
        }
        action && action(item);
    };
    const updateSelection = (selection) => {
        if (!setCurrentSelection) {
            return;
        }
        if (multiple) {
            setCurrentSelection(selection);
        }
        else {
            setCurrentSelection(selection);
        }
    };
    const handlerSelect = (item) => {
        setSelected((prevState) => {
            if (!multiple) {
                const newSelected = prevState
                    ? prevState[id] === item[id]
                        ? undefined
                        : item
                    : item;
                updateSelection(newSelected);
                return newSelected;
            }
            const newSelected = prevState
                ? {
                    ...prevState,
                }
                : {};
            const index = getIndex(item[id]);
            if (newSelected[index]) {
                delete newSelected[index];
            }
            else {
                newSelected[index] = item;
            }
            updateSelection(newSelected);
            return newSelected;
        });
    };
    const handlerSelectAll = () => {
        if (!multiple) {
            return;
        }
        setSelected((prevState) => {
            const newSelected = prevState
                ? {
                    ...prevState,
                }
                : {};
            data.forEach((item) => {
                const index = getIndex(item[id]);
                if (selectAll) {
                    delete newSelected[index];
                }
                else {
                    newSelected[index] = item;
                }
            });
            updateSelection(newSelected);
            return newSelected;
        });
    };
    useEffect(() => {
        if (!multiple) {
            return;
        }
        setSelectAll(data.every((item) => {
            const index = getIndex(item[id]);
            return selected.hasOwnProperty(index);
        }));
    }, [selected, data]);
    useEffect(() => {
        setSelected(multiple ? currentSelection ?? {} : currentSelection);
    }, [currentSelection]);
    return (<div {...restProps} className={clsx('overflow-x-auto', restProps.className)}>
      <table {...tableProps} className={clsx('w-full min-w-full text-left', tableProps?.className)}>
        <thead>
          <tr className="border-gray-5 border-b text-xs">
            {!!selectable && !!multiple && (<th className="px-4 py-3">
                <Checkbox label={{ className: 'hidden' }} checkbox={{
                checked: selectAll,
                onChange: handlerSelectAll,
            }}/>
              </th>)}
            <Each of={headers} render={({ title, key }) => (<th key={key} className="px-4 py-3">
                  {title}
                </th>)}/>
          </tr>
        </thead>
        {!!data.length && (<tbody>
            <Show>
              <Show.When isTrue={loading}>
                <TableSkeleton numberOfRows={numberOfRows} numberOfColumns={headers.length}/>
              </Show.When>
              <Show.Else>
                <Each of={data} render={(item) => {
                const index = getIndex(item[id]);
                const isSelected = selected
                    ? multiple
                        ? !!selected[index]
                        : selected[id] === index
                    : false;
                return (<tr key={index} className={clsx('border-gray-5 border-b transition-colors', !isSelected ? 'hover:bg-gray-5' : 'bg-gray-4', (action || (selectable && !multiple)) &&
                        'cursor-pointer')} onClick={(event) => handlerClick(event, item)}>
                        {!!selectable && !!multiple && (<td className="px-4 py-3">
                            <Checkbox label={{ className: 'hidden' }} checkbox={{
                            checked: isSelected,
                            onChange: () => handlerSelect(item),
                        }}/>
                          </td>)}
                        <Each of={headers} render={({ key }) => (<td key={key} className="p-4">
                              {renderTableCellContent(item[key])}
                            </td>)}/>
                        {!!actions && (<td className="p-4">
                            <div className="flex cursor-pointer justify-end gap-2">
                              <Each of={actions(item)} render={({ children, dropdown, tooltip, ...restProps }, index) => {
                            return (<Show key={index}>
                                      <Show.When isTrue={dropdown !== undefined}>
                                        <Dropdown actions={dropdown?.actions} className="top-full -left-[120px]">
                                          <div className={buttonClass}>
                                            {dropdown
                                    ?.children}
                                          </div>
                                        </Dropdown>
                                      </Show.When>
                                      <Show.When isTrue={Boolean(tooltip)}>
                                        <Tooltip message={tooltip} placement="top">
                                          <button {...restProps} className={buttonClass}>
                                            {children}
                                          </button>
                                        </Tooltip>
                                      </Show.When>
                                      <Show.Else>
                                        <button {...restProps} className={buttonClass}>
                                          {children}
                                        </button>
                                      </Show.Else>
                                    </Show>);
                        }}/>
                            </div>
                          </td>)}
                      </tr>);
            }}/>
                {!!footer && <tr className="bg-gray-6">{footer}</tr>}
              </Show.Else>
            </Show>
          </tbody>)}
      </table>
      {!data.length && <TableEmpty />}
    </div>);
}
//# sourceMappingURL=Table.jsx.map