import type {
  AccessorKeyColumnDef,
  Cell,
  ColumnFiltersState,
  ColumnSort,
  RowData,
  Table,
} from '@tanstack/react-table';
import type { CellTypes, SortOrder } from './constants';
import type { StylesConfig } from 'react-select';
import type { PaginationProps } from '../pagination';
import { BaseOption, CustomSelectProps } from '../select/customSelect';

declare module '@tanstack/react-table' {
  // biome-ignore lint/correctness/noUnusedVariables: <explanation>
  interface TableMeta<TData extends RowData> {
    updateData: (rowIndex: string, columnId: keyof TData | '', value: unknown) => void;
  }
}

export type EditableTableColumnDef<TData> = Omit<AccessorKeyColumnDef<TData, any>, 'meta'> & {
  meta?: ColumnMeta<TData>;
  accessorKey: keyof TData | ''; // required now
  columnType?: 'td' | 'th';
};

export type EditableTableProps<TData> = {
  tableId?: string;
  classNames?: {
    wrapper?: string;
    tableWrapper?: string;
    table?: string;
  };

  tableName: string;
  data: TData[];
  columns: EditableTableColumnDef<TData>[];
  isLoading: boolean;
  handleSaveData: (data: SaveData<TData>) => void;
  idSelector: (data: TData) => string;

  selectAllCheckBoxName?: string;
  setTable?: (table: Table<TData>) => void;
  setColumnFilters?: (value: ColumnFiltersState) => void;
  hiddenColumnIds?: string[];
  isCellDisabled?: (data: TData, column: EditableTableColumnDef<TData>['id']) => boolean;

  // server pagination
  showPagination?: boolean;
  serverPagination?: boolean;
  totalCount?: number;
  currentPage?: number;
  onPageChange?: (page: number) => void;
  currentPageSize?: number;
  onPageSizeChange?: (limit: number) => void;
  defaultSortingHeaders?: ColumnSort[];
  handleSort?: (sortData: { columnId: string; order: SortOrder }) => void;
  globalFilter?: string;
  setGlobalFilter?: (value: any) => void;
  paginationSizeOptions?: PaginationProps['sizeOptions'];

  //Footer props
  showTableFooter?: boolean;

  //Selection
  onSelectionChange?: (ids: string[]) => void;
};

export type GroupedEditableTableProps<TData> = Omit<EditableTableProps<TData>, 'data'> & {
  data: { groupId: string; groupName: string; data: TData[]; description?: string }[];
  allowBulkGroupSelection: boolean;
};

export type EditableTableCellProps<TData> = {
  cell: Cell<TData, unknown>;
  isCellDisabled?: EditableTableProps<TData>['isCellDisabled'];
};

export interface SaveData<TData> {
  rowId: string;
  columnId: string;
  accessorKey: keyof TData | '';
  value: string | number | boolean;
  groupId?: string;
}

export type ColumnMeta<TData> = (
  | CheckBoxMetaData<TData>
  | LinkMetaData
  | MultiSelectMetaData<TData>
  | TextInputMetaData<TData>
  | SelectMetaData<TData>
  | SwitchMetaData<TData>
) &
  FooterMeta;

export interface CheckBoxMetaData<TData> {
  type: 'checkbox';
  label?: (data: TData) => string;
}

export interface LinkMetaData {
  type: 'link';
}

export interface MultiSelectMetaData<TData> {
  type: 'multiselect';
  placeholder: string;
  label?: (data: TData) => string;
  options: { label: string; value: string | number }[];
  customStyles?: StylesConfig<MultiSelectMetaData<TData>['options'][0], true>;
}

export interface TextInputMetaData<TData> {
  type: 'text' | 'date' | 'number';
  placeholder: string;
  label?: (data: TData) => string;
  step?: number;
}

export interface SelectMetaData<TData> {
  type: 'select';
  placeholder: string;
  label?: (data: TData) => string;
  options: BaseOption[];
  renderCustomLabel?: CustomSelectProps['renderCustomLabel'];
}

export interface SwitchMetaData<TData> {
  type: 'switch';
  label?: (data: TData) => string;
  activeText?: string;
  inactiveText?: string;
}

export interface FooterMeta {
  footerType?: 'addition' | 'average' | 'isTotalField';
}

export interface Row<TData> {
  getValue(columnId: string): unknown;
  original: TData;
}

export interface FocusData {
  rowId: string | null;
  columnIndex: number;
  cellType: CellTypes;
  groupId: string | null;
  rowIndex: number;
}

export interface FocusHandlerContextType {
  focusedCell: FocusData;
  setFocusedCell: (focusData: FocusData) => void;
}

export interface TableContextType<TData> {
  handleSaveData: EditableTableProps<TData>['handleSaveData'];
  idSelector: EditableTableProps<TData>['idSelector'];
  table: Table<TData>;
  tableName: string;
  groupData: { groupName: string; groupId: string; ids: string[]; description?: string }[];
  allowBulkGroupSelection: boolean;
  tableRef: React.RefObject<HTMLTableElement>;
  doesRowHeaderExist: boolean;
  hasFooter: boolean;
  serverPagination: boolean;
}

export interface UseFocusHandlerProps {
  cellType: CellTypes;
  rowId: string | null;
  columnIndex: number;
  groupId: string | null;
  rowIndex: number;
}

export interface FocusHookReturnType {
  focusedCell: FocusData;
  setFocusedCell: (focusData: FocusData) => void;
  tableRef: React.RefObject<HTMLTableElement>;
  isCurrentCellFocused: boolean;
  focusCurrentCell: () => void;
}

export type TDataWithGroupId<TData> = TData & {
  editableTableGroupId: string;
};

export interface EditableTablePaginationProps<TData> {
  totalResults: number;
  pagination: {
    pageIndex: number;
    pageSize: number;
  };
  table: Table<TData>;
  onPageChange?: (page: number) => void;
  onPageSizeChange?: (limit: number) => void;
  paginationSizeOptions?: PaginationProps['sizeOptions'];
}
