export type RowClickSelectionAction = 'deselect' | 'select';

interface SelectionColumn {
  field?: string;
  flag?: string;
  type?: string;
}

interface RowClickSelectionContext<TRow, TKey> {
  deselectRow: (rowKey: TKey) => void;
  getRowKey: () => ((row: TRow) => TKey) | string;
  getSelectedRowKeys: () => readonly TKey[];
  isEnabled: () => boolean;
  selectRows: (rows: TRow[]) => void;
}

interface RowClickSelectionEvent<TRow> {
  column?: null | SelectionColumn;
  row: TRow;
}

export function isCheckboxSelectionColumn(column?: null | SelectionColumn) {
  return column?.type === 'checkbox' || column?.flag === 'checkbox';
}

export function isActionColumn(column?: null | SelectionColumn) {
  return column?.field === 'action' || column?.flag === 'action';
}

export function resolveRowClickSelectionAction<TKey>(selectedRowKeys: readonly TKey[], clickedRowKey: TKey): RowClickSelectionAction {
  return selectedRowKeys.includes(clickedRowKey) ? 'deselect' : 'select';
}

export function getDynamicListSelectionConfig(hasBatchSelection: boolean, isTreeTable: boolean) {
  if (!hasBatchSelection) return {};
  const rowSelection = { type: 'checkbox' as const };
  if (!isTreeTable) return { rowSelection };
  return {
    checkboxConfig: { checkStrictly: true, showHeader: true },
    rowSelection,
  };
}

export function createRowClickSelectionHandler<TRow, TKey>(context: RowClickSelectionContext<TRow, TKey>) {
  return ({ column, row }: RowClickSelectionEvent<TRow>) => {
    if (!context.isEnabled() || isCheckboxSelectionColumn(column) || isActionColumn(column)) return;
    const rowKey = context.getRowKey();
    const clickedRowKey = typeof rowKey === 'function' ? rowKey(row) : (row as unknown as Record<string, null | TKey | undefined>)[rowKey];
    if (clickedRowKey === undefined || clickedRowKey === null) return;

    const action = resolveRowClickSelectionAction(context.getSelectedRowKeys(), clickedRowKey);
    if (action === 'deselect') {
      context.deselectRow(clickedRowKey);
      return;
    }
    context.selectRows([row]);
  };
}
