import { Filter, InputType } from '@/models';
import { isEmptyStringOrNotDefined } from '@/helpers';

export const bmsDefaultSearchFilterFunction = (
  item: unknown,
  searchValue: string,
): boolean =>
  JSON.stringify(Object.values(item as object))
    .toLowerCase()
    .includes(searchValue.toLowerCase());

export const isBetweenFilter = (filter: Filter): boolean =>
  filter.type === 'betweenDate' ||
  filter.type === 'betweenNumber' ||
  filter.type === 'betweenDateTime';

export const defaultNumberFilterFunction = (
  itemNumber: number,
  search: number,
  isAfterSearch: boolean,
) => {
  if (
    isEmptyStringOrNotDefined(itemNumber) ||
    isEmptyStringOrNotDefined(search)
  ) {
    return true;
  }
  return isAfterSearch ? itemNumber >= search : itemNumber <= search;
};
export const defaultIsAfterDateFilterFunction = (
  dateItem: Date,
  search: Date,
  isGreaterThan: boolean,
) => {
  if (!dateItem || !search) {
    return true;
  }
  return isGreaterThan
    ? dateItem.getTime() >= search.getTime()
    : dateItem.getTime() <= search.getTime();
};

export const dateFilterCompare = (
  itemDate: string,
  filter: Filter,
  isGreaterThan = true,
) => {
  const sanitizedItemDate = new Date(itemDate);
  const searchDate = isEmptyStringOrNotDefined(filter.value)
    ? null
    : new Date(filter.value);

  // in date mode, we are more tolerant for search on time (for "locale" purpose)
  if (filter.inputType === InputType.DATE) {
    sanitizedItemDate.setHours(+2, 0, 0, 0);
    searchDate?.setHours(0, 0, 0, 0);
  }
  const applyFilter = filter.customFilter
    ? filter.customFilter
    : defaultIsAfterDateFilterFunction;

  return applyFilter(sanitizedItemDate, searchDate, isGreaterThan);
};

export const dateIsBetween = (itemDate: string, filter: Filter) => {
  const sanitizedItemDate = new Date(itemDate);
  const fromDate = isEmptyStringOrNotDefined(filter.valueFrom)
    ? null
    : new Date(filter.valueFrom);
  const toDate = isEmptyStringOrNotDefined(filter.valueTo)
    ? null
    : new Date(filter.valueTo);
  // in date mode, we are more tolerant for search on time (for "locale" purpose)
  if (filter.type === 'betweenDate') {
    if (fromDate) fromDate.setHours(-2, 0, 0, 0);
    if (toDate) toDate.setHours(+2, 0, 0, 0);
    if (toDate) toDate.setHours(23, 59, 59, 0);
  }

  const applyFilter = filter.customFilter
    ? filter.customFilter
    : defaultIsAfterDateFilterFunction;

  //we have at least one of the 2 fields from/to with a value
  const isValidFrom = fromDate
    ? applyFilter(sanitizedItemDate, fromDate, true)
    : true;
  const isValidTo = toDate
    ? applyFilter(sanitizedItemDate, toDate, false)
    : true;
  return isValidFrom && isValidTo;
};

export const numberIsBetween = (itemValue: any, filter: Filter) => {
  if (Number.isNaN(itemValue)) {
    return true;
  }
  const applyFilter = filter.customFilter
    ? filter.customFilter
    : defaultNumberFilterFunction;
  //we have at least one of the 2 fields from/to with a value
  const isValidFrom =
    filter.valueFrom === null ||
    filter.valueFrom === undefined ||
    applyFilter(Number(itemValue), Number(filter.valueFrom), true);
  const isValidTo =
    filter.valueTo === null ||
    filter.valueTo === undefined ||
    applyFilter(Number(itemValue), Number(filter.valueTo), false);
  return isValidFrom && isValidTo;
};
