import { describe, expect, it } from 'vitest';

import {
  createRowClickSelectionHandler,
  getDynamicListSelectionConfig,
  isActionColumn,
  isCheckboxSelectionColumn,
  resolveRowClickSelectionAction,
} from '../helpers/rowSelection';

interface TestRow {
  id: string;
}

function createSelectionHarness(initialSelectedRowKeys: string[]) {
  let selectedRowKeys = [...initialSelectedRowKeys];
  const handleRowSelection = createRowClickSelectionHandler<TestRow, string>({
    deselectRow: (rowKey) => {
      selectedRowKeys = selectedRowKeys.filter((key) => key !== rowKey);
    },
    getRowKey: () => 'id',
    getSelectedRowKeys: () => selectedRowKeys,
    isEnabled: () => true,
    selectRows: (rows) => {
      selectedRowKeys = [...selectedRowKeys, ...rows.map((row) => row.id)];
    },
  });

  return {
    getSelectedRowKeys: () => selectedRowKeys,
    handleRowSelection,
  };
}

describe('resolveRowClickSelectionAction', () => {
  it('selects an unselected clicked row without replacing other selections', () => {
    expect(resolveRowClickSelectionAction(['row-1', 'row-2'], 'row-3')).toBe('select');
  });

  it('deselects a clicked row when it is the only selection', () => {
    expect(resolveRowClickSelectionAction(['row-1'], 'row-1')).toBe('deselect');
  });

  it('deselects a clicked selected row while other rows are selected', () => {
    expect(resolveRowClickSelectionAction(['row-1', 'row-2'], 'row-2')).toBe('deselect');
  });
});

describe('isCheckboxSelectionColumn', () => {
  it('recognizes checkbox columns and leaves ordinary columns to row-click handling', () => {
    expect(isCheckboxSelectionColumn({ type: 'checkbox' })).toBe(true);
    expect(isCheckboxSelectionColumn({ flag: 'checkbox' })).toBe(true);
    expect(isCheckboxSelectionColumn({ field: 'name' })).toBe(false);
  });
});

describe('isActionColumn', () => {
  it('recognizes action columns by field or flag', () => {
    expect(isActionColumn({ field: 'action' })).toBe(true);
    expect(isActionColumn({ flag: 'action' })).toBe(true);
    expect(isActionColumn({ field: 'name' })).toBe(false);
  });
});

describe('createRowClickSelectionHandler', () => {
  it('selects an unselected clicked row and preserves previous selections', () => {
    const harness = createSelectionHarness(['row-1', 'row-2']);

    harness.handleRowSelection({ column: { field: 'name' }, row: { id: 'row-3' } });

    expect(harness.getSelectedRowKeys()).toEqual(['row-1', 'row-2', 'row-3']);
  });

  it('deselects the clicked row and preserves other selected rows', () => {
    const harness = createSelectionHarness(['row-1', 'row-2']);

    harness.handleRowSelection({ column: { field: 'name' }, row: { id: 'row-2' } });

    expect(harness.getSelectedRowKeys()).toEqual(['row-1']);
  });

  it('clears selection when the only selected row is clicked', () => {
    const harness = createSelectionHarness(['row-1']);

    harness.handleRowSelection({ column: { field: 'name' }, row: { id: 'row-1' } });

    expect(harness.getSelectedRowKeys()).toEqual([]);
  });

  it('leaves checkbox clicks to the existing checkbox behavior', () => {
    const harness = createSelectionHarness(['row-1']);

    harness.handleRowSelection({ column: { type: 'checkbox' }, row: { id: 'row-2' } });

    expect(harness.getSelectedRowKeys()).toEqual(['row-1']);
  });

  it('does not change selection when an action cell is clicked', () => {
    const harness = createSelectionHarness(['row-1']);

    harness.handleRowSelection({ column: { field: 'action', flag: 'action' }, row: { id: 'row-2' } });

    expect(harness.getSelectedRowKeys()).toEqual(['row-1']);
  });
});

describe('getDynamicListSelectionConfig', () => {
  it('does not add selection config when the list has no batch actions', () => {
    expect(getDynamicListSelectionConfig(false, false)).toEqual({});
  });

  it('keeps the existing checkbox config for flat lists', () => {
    expect(getDynamicListSelectionConfig(true, false)).toEqual({ rowSelection: { type: 'checkbox' } });
  });

  it('prevents tree checkbox cascades while keeping header select-all visible', () => {
    expect(getDynamicListSelectionConfig(true, true)).toEqual({
      checkboxConfig: { checkStrictly: true, showHeader: true },
      rowSelection: { type: 'checkbox' },
    });
  });
});
