import { ControlType, GamaPropModel } from '@win2win/shared';
import { isNil, omit, values } from 'lodash';
import { validateCatastro } from './validators';

export const ControlValidatorsMap: Record<
  string,
  {
    fn: (val?: number | string) => (control: GamaPropModel) => boolean;
    message: string;
  }
> = {
  required: {
    fn: () => (control: GamaPropModel) => {
      if (control.controlType === ControlType.LOCATION) {
        const { value } = control.value;
        return values(omit(value, 'catastro')).every((v) => !isNil(v) && v !== '') && (value?.catastro ? validateCatastro(value?.catastro) : true);
      }
      if (control.controlType === ControlType.DYNAMIC_ARRAY || control.multiple) {
        return (control.value?.length || 0) > 0;
      }
      if (control.controlType === ControlType.KEYS_COUNTER) {
        const counters = values(control.value);
        return counters.some((counter) => counter > 0);
      }
      return !isNil(control.value) && control.value !== '';
    },
    message: 'Este campo es requerido',
  },
  min: {
    fn: (min) => (control: GamaPropModel) => {
      if (min === undefined || isNaN(Number(min))) return true;
      return compareInequalty(control, '>=', Number(min));
    },
    message: 'El valor es menor al mínimo permitido',
  },
  max: {
    fn: (max) => (control: GamaPropModel) => {
      if (max === undefined || isNaN(Number(max))) return true;
      return compareInequalty(control, '<=', Number(max));
    },
    message: 'El valor es mayor al máximo permitido',
  },
  onlyNumbers: {
    fn: () => (control: GamaPropModel) => {
      return /^[0-9]*$/.test(String(control.value) || '');
    },
    message: 'Este campo solo acepta números',
  },
  email: {
    fn: () => (control: GamaPropModel) => {
      if (!control.value) return true;
      return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(String(control.value) || '');
    },
    message: 'El correo electrónico no es válido',
  },
  url: {
    fn: () => (control: GamaPropModel) => {
      if (!control.value) return true;
      return /^(ftp|http|https):\/\/[^ "]+$/.test(String(control.value) || '') || /^www\.[^ "]+$/.test(String(control.value) || '');
    },
    message: 'La URL no es válida',
  },
};

function compareInequalty(control: GamaPropModel, symbol: '>' | '<' | '>=' | '<=', compareValue: number) {
  const operation = {
    '>': (a, b) => a > b,
    '<': (a, b) => a < b,
    '>=': (a, b) => a >= b,
    '<=': (a, b) => a <= b,
  }[symbol];
  if (control.controlType === ControlType.NUMBER) {
    const value = Number(control.value);
    return operation(value, compareValue);
  }
  if (control.controlType === ControlType.TEXT) {
    const value = (control.value || '').length;
    return operation(value, compareValue);
  }
  if ([ControlType.CARDS_SELECT, ControlType.SELECT].includes(control.controlType as ControlType) && control.multiple) {
    const value = (control.value || []).length;
    return operation(value, compareValue);
  }
  return false;
}
