import { ReactNode, CSSProperties, HTMLAttributes, TdHTMLAttributes, ThHTMLAttributes } from 'react';

export type TableVariant = 'default' | 'striped' | 'bordered' | 'minimal' | 'card-style' | 'compact';
export type TableSize = 'sm' | 'md' | 'lg';
export type TableStatus = 'default' | 'success' | 'warning' | 'error' | 'info';
export type SortDirection = 'asc' | 'desc' | null;
export type SelectionMode = 'none' | 'single' | 'multiple';
export type EditMode = 'none' | 'cell' | 'row' | 'inline';
export type FilterMatchMode = 'contains' | 'startsWith' | 'endsWith' | 'equals' | 'notEquals' | 'custom';
export type PaginationMode = 'client' | 'server';
export type AnimationType = 'fade' | 'slide' | 'scale' | 'none';
export interface ColumnDef<TData = RowData> {
    id: string;
    accessorKey?: keyof TData | string;
    accessorFn?: (row: TData) => unknown;
    header?: string | ((props: {
        column: ColumnDef<TData>;
    }) => ReactNode);
    cell?: (props: {
        value: unknown;
        row: TData;
        column: ColumnDef<TData>;
        rowIndex: number;
    }) => ReactNode;
    footer?: string | ((props: {
        column: ColumnDef<TData>;
    }) => ReactNode);
    width?: number | string;
    minWidth?: number;
    maxWidth?: number;
    sortable?: boolean;
    sortingFn?: (rowA: TData, rowB: TData, columnId: string) => number;
    filterable?: boolean;
    filterFn?: (row: TData, columnId: string, filterValue: unknown) => boolean;
    editable?: boolean;
    editComponent?: (props: {
        value: unknown;
        row: TData;
        column: ColumnDef<TData>;
        onSave: (value: unknown) => void;
        onCancel: () => void;
    }) => ReactNode;
    align?: 'left' | 'center' | 'right';
    className?: string;
    headerClassName?: string;
    cellClassName?: string | ((props: {
        row: TData;
        value: unknown;
    }) => string);
    footerClassName?: string;
    sticky?: 'left' | 'right';
    hidden?: boolean;
    group?: string;
    meta?: Record<string, unknown>;
}
export interface SortDescriptor {
    columnId: string;
    direction: SortDirection;
}
export interface FilterDescriptor {
    columnId: string;
    value: unknown;
    matchMode?: FilterMatchMode;
}
export type SelectionModel = Set<string | number>;
export interface PaginationState {
    pageIndex: number;
    pageSize: number;
}
export type ExpandedState = Set<string | number>;
export interface EditingState {
    rowId: string | number;
    columnId: string;
    value: unknown;
}
export interface GroupDef<TData = RowData> {
    columnId: string;
    aggregationFn?: (rows: TData[]) => unknown;
    header?: (props: {
        group: GroupDef<TData>;
        rows: TData[];
        value: unknown;
    }) => ReactNode;
}
export interface RowData {
    id: string | number;
    [key: string]: unknown;
}
export interface TableBaseProps<TData extends RowData = RowData> {
    data: TData[];
    columns: ColumnDef<TData>[];
    getRowId?: (row: TData, index: number) => string | number;
    variant?: TableVariant;
    size?: TableSize;
    loading?: boolean;
    loadingComponent?: ReactNode;
    empty?: boolean;
    emptyComponent?: ReactNode;
    disabled?: boolean;
    selectionMode?: SelectionMode;
    selectedRows?: SelectionModel;
    defaultSelectedRows?: SelectionModel;
    onSelectionChange?: (selection: SelectionModel) => void;
    isRowSelectable?: (row: TData) => boolean;
    enableSorting?: boolean;
    sort?: SortDescriptor[];
    defaultSort?: SortDescriptor[];
    onSortChange?: (sort: SortDescriptor[]) => void;
    enableMultiSort?: boolean;
    maxMultiSortColCount?: number;
    enableFiltering?: boolean;
    filters?: FilterDescriptor[];
    defaultFilters?: FilterDescriptor[];
    onFiltersChange?: (filters: FilterDescriptor[]) => void;
    globalFilter?: string;
    onGlobalFilterChange?: (value: string) => void;
    enablePagination?: boolean;
    paginationMode?: PaginationMode;
    pagination?: PaginationState;
    defaultPagination?: PaginationState;
    onPaginationChange?: (pagination: PaginationState) => void;
    totalCount?: number;
    pageSizeOptions?: number[];
    enableExpanding?: boolean;
    expandedRows?: ExpandedState;
    defaultExpandedRows?: ExpandedState;
    onExpandedChange?: (expanded: ExpandedState) => void;
    expandedContent?: (props: {
        row: TData;
        rowIndex: number;
    }) => ReactNode;
    editMode?: EditMode;
    editingCell?: EditingState | null;
    onEditingCellChange?: (editing: EditingState | null) => void;
    onEditCommit?: (rowId: string | number, columnId: string, value: unknown, row: TData) => void | Promise<void>;
    onEditCancel?: (rowId: string | number, columnId: string) => void;
    enableGrouping?: boolean;
    groupBy?: string[];
    groups?: GroupDef<TData>[];
    enableVirtualization?: boolean;
    virtualizer?: unknown;
    enableColumnResizing?: boolean;
    enableColumnReordering?: boolean;
    enableRowReordering?: boolean;
    stickyHeader?: boolean;
    stickyColumns?: boolean;
    onRowClick?: (row: TData, rowIndex: number, event: React.MouseEvent) => void;
    onRowDoubleClick?: (row: TData, rowIndex: number, event: React.MouseEvent) => void;
    onCellClick?: (row: TData, column: ColumnDef<TData>, rowIndex: number, event: React.MouseEvent) => void;
    onCellDoubleClick?: (row: TData, column: ColumnDef<TData>, rowIndex: number, event: React.MouseEvent) => void;
    rowRenderer?: (props: {
        row: TData;
        rowIndex: number;
        children: ReactNode;
    }) => ReactNode;
    noDataRenderer?: () => ReactNode;
    loadingRenderer?: () => ReactNode;
    animationType?: AnimationType;
    animationDuration?: number;
    borderWidth?: string;
    borderColor?: string;
    borderStyle?: string;
    borderRadius?: string;
    fontSize?: string;
    fontWeight?: string;
    fontFamily?: string;
    textColor?: string;
    headerTextColor?: string;
    backgroundColor?: string;
    headerBackgroundColor?: string;
    footerBackgroundColor?: string;
    rowHoverBackground?: string;
    rowSelectedBackground?: string;
    alternateRowBackground?: string;
    focusRingColor?: string;
    focusRingWidth?: string;
    focusRingOffset?: string;
    focusBorderColor?: string;
    focusBackgroundColor?: string;
    boxShadow?: string;
    focusBoxShadow?: string;
    padding?: string;
    paddingX?: string;
    paddingY?: string;
    headerPadding?: string;
    cellPadding?: string;
    footerPadding?: string;
    headerStyle?: CSSProperties;
    headerClassName?: string;
    bodyStyle?: CSSProperties;
    bodyClassName?: string;
    footerStyle?: CSSProperties;
    footerClassName?: string;
    rowStyle?: CSSProperties | ((row: TData, rowIndex: number) => CSSProperties);
    rowClassName?: string | ((row: TData, rowIndex: number) => string);
    cellStyle?: CSSProperties | ((row: TData, column: ColumnDef<TData>) => CSSProperties);
    cellClassName?: string | ((row: TData, column: ColumnDef<TData>) => string);
    sortAscIcon?: ReactNode;
    sortDescIcon?: ReactNode;
    sortNeutralIcon?: ReactNode;
    expandIcon?: ReactNode;
    collapseIcon?: ReactNode;
    selectIcon?: ReactNode;
    selectAllIcon?: ReactNode;
    filterIcon?: ReactNode;
    clearFilterIcon?: ReactNode;
    'aria-label'?: string;
    'aria-labelledby'?: string;
    'aria-describedby'?: string;
    captionComponent?: ReactNode;
}
export interface TableContextValue<TData extends RowData = RowData> {
    data: TData[];
    columns: ColumnDef<TData>[];
    getRowId: (row: TData, index: number) => string | number;
    variant: TableVariant;
    size: TableSize;
    loading: boolean;
    empty: boolean;
    disabled: boolean;
    selectionMode: SelectionMode;
    selectedRows: SelectionModel;
    setSelectedRows: (selection: SelectionModel | ((prev: SelectionModel) => SelectionModel)) => void;
    isRowSelectable?: (row: TData) => boolean;
    toggleRowSelection: (rowId: string | number) => void;
    toggleAllRowsSelection: () => void;
    enableSorting: boolean;
    sort: SortDescriptor[];
    setSort: (sort: SortDescriptor[] | ((prev: SortDescriptor[]) => SortDescriptor[])) => void;
    toggleSort: (columnId: string, multiSort?: boolean) => void;
    enableFiltering: boolean;
    filters: FilterDescriptor[];
    setFilters: (filters: FilterDescriptor[] | ((prev: FilterDescriptor[]) => FilterDescriptor[])) => void;
    globalFilter: string;
    setGlobalFilter: (value: string) => void;
    enablePagination: boolean;
    paginationMode: PaginationMode;
    pagination: PaginationState;
    setPagination: (pagination: PaginationState | ((prev: PaginationState) => PaginationState)) => void;
    totalCount: number;
    pageSizeOptions: number[];
    pageCount: number;
    canPreviousPage: boolean;
    canNextPage: boolean;
    enableExpanding: boolean;
    expandedRows: ExpandedState;
    setExpandedRows: (expanded: ExpandedState | ((prev: ExpandedState) => ExpandedState)) => void;
    toggleRowExpansion: (rowId: string | number) => void;
    expandedContent?: (props: {
        row: TData;
        rowIndex: number;
    }) => ReactNode;
    editMode: EditMode;
    editingCell: EditingState | null;
    setEditingCell: (editing: EditingState | null) => void;
    startEditing: (rowId: string | number, columnId: string) => void;
    commitEdit: (value: unknown) => void;
    cancelEdit: () => void;
    enableGrouping: boolean;
    groupBy: string[];
    groups: GroupDef<TData>[];
    processedData: TData[];
    paginatedData: TData[];
    animationType: AnimationType;
    animationDuration: number;
    styles: Record<string, unknown>;
    icons: {
        sortAsc?: ReactNode;
        sortDesc?: ReactNode;
        sortNeutral?: ReactNode;
        expand?: ReactNode;
        collapse?: ReactNode;
        select?: ReactNode;
        selectAll?: ReactNode;
        filter?: ReactNode;
        clearFilter?: ReactNode;
    };
    headerStyle?: CSSProperties;
    bodyStyle?: CSSProperties;
    footerStyle?: CSSProperties;
    rowStyle?: CSSProperties | ((row: TData, rowIndex: number) => CSSProperties);
    rowClassName?: string | ((row: TData, rowIndex: number) => string);
    cellStyle?: CSSProperties | ((row: TData, column: ColumnDef<TData>) => CSSProperties);
    cellClassName?: string | ((row: TData, column: ColumnDef<TData>) => string);
    stickyHeader?: boolean;
    rowRenderer?: (props: {
        row: TData;
        rowIndex: number;
        children: ReactNode;
    }) => ReactNode;
    onRowClick?: (row: TData, rowIndex: number, event: React.MouseEvent) => void;
    onRowDoubleClick?: (row: TData, rowIndex: number, event: React.MouseEvent) => void;
    onCellClick?: (row: TData, column: ColumnDef<TData>, rowIndex: number, event: React.MouseEvent) => void;
    onCellDoubleClick?: (row: TData, column: ColumnDef<TData>, rowIndex: number, event: React.MouseEvent) => void;
}
export interface TableProps<TData extends RowData = RowData> extends Omit<HTMLAttributes<HTMLTableElement>, 'onSelect' | 'onChange'>, TableBaseProps<TData> {
}
export type TableHeaderProps = ThHTMLAttributes<HTMLTableSectionElement>;
export type TableBodyProps = HTMLAttributes<HTMLTableSectionElement>;
export type TableFooterProps = HTMLAttributes<HTMLTableSectionElement>;
export interface TableRowProps extends HTMLAttributes<HTMLTableRowElement> {
    status?: TableStatus;
    selected?: boolean;
    expanded?: boolean;
    disabled?: boolean;
}
export interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {
    status?: TableStatus;
}
export interface TableHeaderCellProps extends ThHTMLAttributes<HTMLTableCellElement> {
    sorted?: SortDirection;
    sortable?: boolean;
    resizable?: boolean;
    reorderable?: boolean;
}
export interface TablePaginationProps extends HTMLAttributes<HTMLDivElement> {
    showPageSizeSelector?: boolean;
    showPageNumbers?: boolean;
    showTotalCount?: boolean;
    compact?: boolean;
}
export interface TableFilterProps extends HTMLAttributes<HTMLDivElement> {
    column: ColumnDef<RowData>;
    value: unknown;
    onChange: (value: unknown) => void;
    matchMode?: FilterMatchMode;
    placeholder?: string;
}
export interface TableGlobalFilterProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
    value: string;
    onChange: (value: string) => void;
    placeholder?: string;
    debounceMs?: number;
}
export interface TableSortIconProps extends HTMLAttributes<HTMLSpanElement> {
    direction: SortDirection;
}
export interface TableExpandButtonProps extends HTMLAttributes<HTMLButtonElement> {
    expanded: boolean;
    onToggle: () => void;
}
export interface TableSelectCheckboxProps extends Omit<HTMLAttributes<HTMLInputElement>, 'onChange'> {
    checked: boolean;
    indeterminate?: boolean;
    onChange: () => void;
    disabled?: boolean;
}
export interface TableEditCellProps<TData = RowData> {
    value: unknown;
    row: TData;
    column: ColumnDef<TData>;
    onSave: (value: unknown) => void;
    onCancel: () => void;
}
export interface TableEmptyProps extends HTMLAttributes<HTMLDivElement> {
    message?: string;
    action?: ReactNode;
    illustration?: ReactNode;
}
export interface TableLoadingProps extends HTMLAttributes<HTMLDivElement> {
    message?: string;
    showSkeleton?: boolean;
    skeletonRows?: number;
}
export interface TableExpandedPanelProps extends HTMLAttributes<HTMLTableRowElement> {
    colSpan: number;
}
