import { describe, expect, it } from 'vitest';
import { addItem, removeItem } from './DynamicListReducer.actions';

interface Data {
  position?: number;
  id: number;
}

const dataSet: Data[] = [
  { position: 1, id: 1 },
  { position: 2, id: 2 },
  { position: 5, id: 5 },
  { position: 6, id: 6 },
  { position: 7, id: 7 },
  { position: 8, id: 8 },
  { position: 20, id: 20 },
  { position: 100, id: 100 },
];

const addItemCases = [
  {
    title: 'item at the beginning',
    item: { position: 1, id: 999 },
    result: [
      { position: 1, id: 999 },
      { position: 2, id: 1 },
      { position: 3, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item before a sequence',
    item: { position: 4, id: 999 },
    result: [
      { position: 4, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item in the beginning of a sequence',
    item: { position: 5, id: 999 },
    result: [
      { position: 5, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 6, id: 5 },
      { position: 7, id: 6 },
      { position: 8, id: 7 },
      { position: 9, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item in the middle of a sequence',
    item: { position: 6, id: 999 },
    result: [
      { position: 6, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 7, id: 6 },
      { position: 8, id: 7 },
      { position: 9, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item before the end of a sequence',
    item: { position: 8, id: 999 },
    result: [
      { position: 8, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 9, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item at the end of a sequence',
    item: { position: 9, id: 999 },
    result: [
      { position: 9, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item without a sequence',
    item: { position: 50, id: 999 },
    result: [
      { position: 50, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item at the end',
    item: { position: 150, id: 999 },
    result: [
      { position: 150, id: 999 },
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
];

const removeItemCases = [
  {
    title: 'item at the beginning',
    item: dataSet[0],
    result: [
      { position: 1, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item before a sequence',
    item: dataSet[1],
    result: [
      { position: 1, id: 1 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item in the beginning of a sequence',
    item: dataSet[2],
    result: [
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 6 },
      { position: 6, id: 7 },
      { position: 7, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item in the middle of a sequence',
    item: dataSet[3],
    result: [
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 7 },
      { position: 7, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item before the end of a sequence',
    item: dataSet[4],
    result: [
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item at the end of a sequence',
    item: dataSet[5],
    result: [
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item without a sequence',
    item: dataSet[6],
    result: [
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 100, id: 100 },
    ],
  },
  {
    title: 'item at the end',
    item: dataSet[7],
    result: [
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 6, id: 6 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
    ],
  },
];

describe('Dynamic List Reducer Actions', () => {
  it('addItem adds item without position', () => {
    expect(addItem({ id: 999 }, dataSet, undefined)).toStrictEqual([
      ...dataSet,
      { id: 999 },
    ]);
  });

  it.each(addItemCases)('addItem adds $title', ({ item, result }) => {
    expect(addItem(item, dataSet, 'position')).toStrictEqual(result);
  });

  it('removeItem removes item without position', () => {
    expect(removeItem(dataSet[3], dataSet, undefined)).toStrictEqual([
      { position: 1, id: 1 },
      { position: 2, id: 2 },
      { position: 5, id: 5 },
      { position: 7, id: 7 },
      { position: 8, id: 8 },
      { position: 20, id: 20 },
      { position: 100, id: 100 },
    ]);
  });

  it.each(removeItemCases)('removeItem removes $title', ({ item, result }) => {
    expect(removeItem(item, dataSet, 'position')).toStrictEqual(result);
  });
});
