import { cloneDeep } from 'lodash-es';

const INPUT_TABLE_INTERACTIVE_SELECTOR = ['[data-input-table-interactive]', '.ant-table-selection-column', 'a', 'button'].join(',');

export type InputTableSelectedRow<TRow> = [index: number, data: TRow];

/** 按完整子表顺序读取当前选中行，返回最新数据副本，忽略已删除的行。 */
export function getInputTableSelectedRows<TRow, TKey>(
  dataSource: readonly TRow[],
  selectedRowKeys: readonly TKey[],
  getRowKey: (row: TRow) => TKey,
): InputTableSelectedRow<TRow>[] {
  const selectedKeys = new Set(selectedRowKeys);
  const rows: InputTableSelectedRow<TRow>[] = [];
  dataSource.forEach((row, index) => {
    if (selectedKeys.has(getRowKey(row))) rows.push([index, cloneDeep(row)]);
  });
  return rows;
}

interface InputTableCellControlProps {
  detailed?: boolean;
  hasClickHandler?: boolean;
  disabled?: boolean;
  disabledButClickable?: boolean;
  readonly?: boolean;
}

interface InputTableSelection<TRow, TKey> {
  selectedRowKeys: TKey[];
  selectedRows: TRow[];
}

interface InputTableRowClickContext<TRow, TKey> {
  getRowKey: (row: TRow) => null | TKey | undefined;
  getSelectedRowKeys: () => readonly TKey[];
  getSelectedRows: () => readonly TRow[];
  isEnabled: () => boolean;
  isRowReadonly: (row: TRow) => boolean;
  updateSelection: (selection: InputTableSelection<TRow, TKey>) => void;
}

interface InputTableRowClickEvent {
  target: EventTarget | null;
}

export function isInputTableInteractiveTarget(target: EventTarget | null) {
  if (!target || typeof (target as Element).closest !== 'function') return false;
  return !!(target as Element).closest(INPUT_TABLE_INTERACTIVE_SELECTOR);
}

export function isInputTableCellEditable(controlProps: InputTableCellControlProps) {
  return !controlProps.disabled && !controlProps.readonly && !controlProps.detailed;
}

export function getInputTableCellInteractionAttrs(controlProps: InputTableCellControlProps) {
  const hasEnabledClickHandler = controlProps.hasClickHandler && !controlProps.disabled && !controlProps.detailed;
  if (controlProps.disabledButClickable || hasEnabledClickHandler || isInputTableCellEditable(controlProps)) {
    return { 'data-input-table-interactive': '' };
  }
  if (controlProps.disabled) return { 'data-input-table-click-through': '' };
  return {};
}

export function toggleInputTableRowSelection<TRow, TKey>(
  selectedRowKeys: readonly TKey[],
  selectedRows: readonly TRow[],
  clickedRow: TRow,
  getRowKey: (row: TRow) => TKey,
): InputTableSelection<TRow, TKey> {
  const clickedRowKey = getRowKey(clickedRow);
  if (selectedRowKeys.includes(clickedRowKey)) {
    return {
      selectedRowKeys: selectedRowKeys.filter((key) => key !== clickedRowKey),
      selectedRows: selectedRows.filter((row) => getRowKey(row) !== clickedRowKey),
    };
  }
  return {
    selectedRowKeys: [...selectedRowKeys, clickedRowKey],
    selectedRows: [...selectedRows.filter((row) => getRowKey(row) !== clickedRowKey), clickedRow],
  };
}

export function createInputTableRowClickHandler<TRow, TKey>(context: InputTableRowClickContext<TRow, TKey>) {
  return (clickedRow: TRow) => ({
    onClick: (event: InputTableRowClickEvent) => {
      if (!context.isEnabled() || isInputTableInteractiveTarget(event.target)) return;
      const clickedRowKey = context.getRowKey(clickedRow);
      if (clickedRowKey === undefined || clickedRowKey === null || context.isRowReadonly(clickedRow)) return;

      const selection = toggleInputTableRowSelection(
        context.getSelectedRowKeys(),
        context.getSelectedRows(),
        clickedRow,
        (row) => context.getRowKey(row) as TKey,
      );
      context.updateSelection(selection);
    },
  });
}
