/* eslint-disable */
import {
  dateFilterCompare,
  dateIsBetween,
  defaultIsAfterDateFilterFunction,
  defaultNumberFilterFunction,
  bmsDefaultSearchFilterFunction,
  isBetweenFilter,
  numberIsBetween,
} from './search.helper';
import { type Filter, FilterType, InputType } from '@/models';
import { vi, it, expect, afterEach } from 'vitest';

describe('isBetweenInput', () => {
  test('should return true for filter type "betweenDate"', () => {
    const filter = { type: 'betweenDate' } as Filter;
    const result = isBetweenFilter(filter);
    expect(result).toBe(true);
  });

  test('should return true for filter type "betweenNumber"', () => {
    const filter = { type: 'betweenDate' } as Filter;
    const result = isBetweenFilter(filter);
    expect(result).toBe(true);
  });

  test('should return true for filter type "betweenDateTime"', () => {
    const filter = { type: 'betweenDateTime' } as Filter;
    const result = isBetweenFilter(filter);
    expect(result).toBe(true);
  });

  test('should return false for filter type that is not "betweenDate", "betweenNumber", or "betweenDateTime"', () => {
    const filter = { type: 'notBetween' as FilterType } as Filter;
    const result = isBetweenFilter(filter);
    expect(result).toBe(false);
  });
});

describe('dateFilterCompare', () => {
  it('should compare two dates when the search date is defined', () => {
    const filter: Filter = {
      key: '',
      label: '',
      type: 'inputDate',
      value: '2024-10-09',
      inputType: InputType.DATE,
    };
    const result = dateFilterCompare('2024-10-10T12:00:00', filter);
    expect(result).toBe(true);
  });

  it('should handle empty or undefined search date', () => {
    const filter: Filter = {
      key: '',
      label: '',
      type: 'inputDate',
      value: '',
      inputType: InputType.DATE,
    };
    const result = dateFilterCompare('2024-10-10T12:00:00', filter);
    expect(result).toBe(true);
  });

  it('should correctly adjust the time in date mode', () => {
    const filter: Filter = {
      key: '',
      label: '',
      type: 'inputDate',
      value: '2024-10-09',
      inputType: InputType.DATE,
    };
    const result = dateFilterCompare('2024-10-09T23:59:59', filter);
    expect(result).toBe(true);
  });

  it('should return false if itemDate is before searchDate', () => {
    const filter: Filter = {
      key: '',
      label: '',
      type: 'inputDate',
      value: '2024-10-10',
      inputType: InputType.DATE,
    };

    const result = dateFilterCompare('2024-10-09T12:00:00', filter);
    expect(result).toBe(false);
  });

  it('should compare with isGreaterThan = false', () => {
    const filter: Filter = {
      key: '',
      label: '',
      type: 'inputDate',
      value: '2024-10-10',
      inputType: InputType.DATE,
    };

    const result = dateFilterCompare('2024-10-09T12:00:00', filter, false);
    expect(result).toBe(true);
  });
});

describe('defaultIsAfterDateFilterFunction', () => {
  test('should return true if dateItem is null', () => {
    const result = defaultIsAfterDateFilterFunction(
      // @ts-ignore
      null,
      new Date('2023-01-01'),
      true,
    );
    expect(result).toBe(true);
  });

  test('should return true if dateItem is after the search date and isAfterSearch is true', () => {
    const dateItem = new Date('2024-01-01');
    const search = new Date('2023-01-01');
    const result = defaultIsAfterDateFilterFunction(dateItem, search, true);
    expect(result).toBe(true);
  });

  test('should return false if dateItem is before the search date and isAfterSearch is true', () => {
    const dateItem = new Date('2022-01-01');
    const search = new Date('2023-01-01');
    const result = defaultIsAfterDateFilterFunction(dateItem, search, true);
    expect(result).toBe(false);
  });

  test('should return true if dateItem is before the search date and isAfterSearch is false', () => {
    const dateItem = new Date('2022-01-01');
    const search = new Date('2023-01-01');
    const result = defaultIsAfterDateFilterFunction(dateItem, search, false);
    expect(result).toBe(true);
  });

  test('should return false if dateItem is after the search date and isAfterSearch is false', () => {
    const dateItem = new Date('2024-01-01');
    const search = new Date('2023-01-01');
    const result = defaultIsAfterDateFilterFunction(dateItem, search, false);
    expect(result).toBe(false);
  });

  test('should return true if dateItem is the same as the search date and isAfterSearch is true', () => {
    const dateItem = new Date('2023-01-01');
    const search = new Date('2023-01-01');
    const result = defaultIsAfterDateFilterFunction(dateItem, search, true);
    expect(result).toBe(true);
  });

  test('should return true if dateItem is the same as the search date and isAfterSearch is false', () => {
    const dateItem = new Date('2023-01-01');
    const search = new Date('2023-01-01');
    const result = defaultIsAfterDateFilterFunction(dateItem, search, false);
    expect(result).toBe(true);
  });
});

describe('defaultNumberFilterFunction', () => {
  // Cas où itemNumber ou search sont null ou indéfinis
  test('should return true if itemNumber is undefined or null', () => {
    // @ts-ignore
    const result = defaultNumberFilterFunction(null, 5, true);
    expect(result).toBe(true);
  });

  test('should return true if search is undefined or null', () => {
    // @ts-ignore
    const result = defaultNumberFilterFunction(5, null, true);
    expect(result).toBe(true);
  });

  test('should return true if both itemNumber and search are undefined or null', () => {
    // @ts-ignore
    const result = defaultNumberFilterFunction(null, null, true);
    expect(result).toBe(true);
  });

  // Cas où itemNumber ou search est égal à 0
  test('should correctly handle 0 as itemNumber and return false if isAfterSearch is true and search is greater', () => {
    const result = defaultNumberFilterFunction(0, 5, true);
    expect(result).toBe(false);
  });

  test('should correctly handle 0 as search and return true if itemNumber is greater and isAfterSearch is true', () => {
    const result = defaultNumberFilterFunction(5, 0, true);
    expect(result).toBe(true);
  });

  test('should correctly handle 0 as itemNumber and return true if isAfterSearch is false and search is greater', () => {
    const result = defaultNumberFilterFunction(0, 5, false);
    expect(result).toBe(true);
  });

  // Comparaisons normales
  test('should return true if itemNumber is greater than search and isAfterSearch is true', () => {
    const result = defaultNumberFilterFunction(10, 5, true);
    expect(result).toBe(true);
  });

  test('should return false if itemNumber is less than search and isAfterSearch is true', () => {
    const result = defaultNumberFilterFunction(3, 5, true);
    expect(result).toBe(false);
  });

  test('should return true if itemNumber is less than search and isAfterSearch is false', () => {
    const result = defaultNumberFilterFunction(3, 5, false);
    expect(result).toBe(true);
  });

  test('should return false if itemNumber is greater than search and isAfterSearch is false', () => {
    const result = defaultNumberFilterFunction(10, 5, false);
    expect(result).toBe(false);
  });

  // Cas d'égalité
  test('should return true if itemNumber is equal to search regardless of isAfterSearch being true', () => {
    const result = defaultNumberFilterFunction(5, 5, true);
    expect(result).toBe(true);
  });

  test('should return true if itemNumber is equal to search regardless of isAfterSearch being false', () => {
    const result = defaultNumberFilterFunction(5, 5, false);
    expect(result).toBe(true);
  });
});

describe('dateIsBetween', () => {
  const validDate = '2024-01-19T08:27:12Z'; // Date de test
  const filter: Filter = {
    key: '',
    label: '',
    type: 'betweenDate',
    valueFrom: '2024-01-18',
    valueTo: '2024-01-20',
    customFilter: undefined, // not our responsability
  };

  test('should return true if itemDate is within the filter range', () => {
    const result = dateIsBetween(validDate, filter);
    expect(result).toBe(true);
  });

  test('should return true if itemDate and the filter range in the same day', () => {
    const filterOnOneDay = {
      ...filter,
      valueFrom: '2024-01-19',
      valueTo: '2024-01-19',
    };
    const result = dateIsBetween(validDate, filterOnOneDay);
    expect(result).toBe(true);
  });

  test('should return false if itemDate is before the filter range', () => {
    const filterBefore = { ...filter, valueFrom: '2024-01-20T09:00:00Z' };
    const result = dateIsBetween(validDate, filterBefore);
    expect(result).toBe(false);
  });

  test('should return false if itemDate is after the filter range', () => {
    const filterAfter = { ...filter, valueTo: '2024-01-18T08:00:00Z' };
    const result = dateIsBetween(validDate, filterAfter);
    expect(result).toBe(false);
  });

  test('should return true if filter valueFrom is undefined and valueTo in range', () => {
    const filterUndefinedFrom = { ...filter, valueFrom: undefined };
    const result = dateIsBetween(validDate, filterUndefinedFrom);
    expect(result).toBe(true);
  });

  test('should return true if filter valueTo is undefined and valueFrom in range', () => {
    const filterUndefinedTo = { ...filter, valueTo: undefined };
    const result = dateIsBetween(validDate, filterUndefinedTo);
    expect(result).toBe(true);
  });

  test('should return true if filter valueFrom and valueTo are both undefined', () => {
    const filterBothUndefined = {
      ...filter,
      valueFrom: undefined,
      valueTo: undefined,
    };
    const result = dateIsBetween(validDate, filterBothUndefined);
    expect(result).toBe(true); // Because both are undefined
  });
});

describe('numberIsBetween', () => {
  const filter: Filter = {
    label: '',
    type: 'betweenNumber',
    key: 'value',
    valueFrom: 10,
    valueTo: 20,
    customFilter: undefined,
  };

  const itemInRange = 15; // Un item dans la plage
  const itemBelowRange = 5; // Un item en dessous de la plage
  const itemAboveRange = 25; // Un item au-dessus de la plage

  test('should return true if item value is within the filter range', () => {
    const result = numberIsBetween(itemInRange, filter);
    expect(result).toBe(true);
  });

  test('should return false if item value is below the filter range', () => {
    const result = numberIsBetween(itemBelowRange, filter);
    expect(result).toBe(false);
  });

  test('should return false if item value is above the filter range', () => {
    const result = numberIsBetween(itemAboveRange, filter);
    expect(result).toBe(false);
  });

  test('should return true if filter valueFrom is null', () => {
    const filterNullFrom = { ...filter, valueFrom: null };
    const result = numberIsBetween(itemInRange, filterNullFrom);
    expect(result).toBe(true);
  });

  test('should return true if filter valueTo is null', () => {
    const filterNullTo = { ...filter, valueTo: null };
    const result = numberIsBetween(itemInRange, filterNullTo);
    expect(result).toBe(true);
  });

  test('should return true if both filter valueFrom and valueTo are null', () => {
    const filterBothNull = { ...filter, valueFrom: null, valueTo: null };
    const result = numberIsBetween(itemInRange, filterBothNull);
    expect(result).toBe(true); // Because both are null
  });

  test('should handle NaN gracefully', () => {
    const invalidItemValue = NaN;
    const result = numberIsBetween(invalidItemValue, filter);
    expect(result).toBe(true); // all invalid input value is not filter
  });
});

describe('defaultSearchFunction', () => {
  test('should return true when item values include the search string', () => {
    const item = { name: 'Hello', title: 'Hello world' };
    expect(bmsDefaultSearchFilterFunction(item, 'hello')).toBe(true);
  });

  test('should return false when item values do not include the search string', () => {
    const item = { name: 'Hello', title: 'Hello world' };
    expect(bmsDefaultSearchFilterFunction(item, 'xyz')).toBe(false);
  });

  test('should be case insensitive', () => {
    const item = { name: 'Foo', title: 'Bar' };
    expect(bmsDefaultSearchFilterFunction(item, 'FOO')).toBe(true);
  });

  test('should return true for empty search string', () => {
    const item = { name: 'Foo', title: 'Bar' };
    expect(bmsDefaultSearchFilterFunction(item, '')).toBe(true);
  });
});
