import { required, numeric, email, max, min } from 'vee-validate/dist/rules';
import getNumbersFromStringWithMask from '@assets/js/getNumbersFromStringWithMask';
import getOnlyNumbersFromString from '@assets/js/getOnlyNumbersFromString';

import { isValid, parse } from 'date-fns';

const min_value = {
  validate(value, { min }) {
    value = getNumbersFromStringWithMask(value);

    return value >= min;
  },
  params: ['min'],
};

const max_value = {
  validate(value, { max }) {
    value = getNumbersFromStringWithMask(value);

    return value <= max;
  },
  params: ['max'],
};

const cep = {
  validate(value) {
    const cepRegex = /^[0-9]{5}-[0-9]{3}$/;

    if (value) {
      return cepRegex.test(value);
    }
  },
};

const minmax_number = {
  validate(value, { min, max }) {
    value = getNumbersFromStringWithMask(value);

    return value >= min && value <= max;
  },
  params: ['min', 'max'],
};

const target_bigger_than_reference = {
  validate(value, { reference }) {
    const targetValue = getNumbersFromStringWithMask(value);

    if (targetValue) {
      const referenceValue = getNumbersFromStringWithMask(reference);
      return targetValue > referenceValue;
    }
  },
  params: ['reference'],
};

const target_is_duplicated = {
  validate(value, { data, key }) {
    const hasKey = typeof key !== 'undefined';
    const normalizeValue = value =>
      String(value)
        .trim()
        .toUpperCase();

    const isDuplicated = data.filter(
      dataItem => normalizeValue(hasKey ? dataItem[key] : dataItem) === normalizeValue(value)
    );

    return isDuplicated.length <= 1;
  },
  params: ['data', 'key'],
};

const target_is_mandatory = {
  validate(_, { data, key }) {
    const hasKey = typeof key !== 'undefined';

    const isMandatory = data.filter(dataItem => hasKey && parseInt(dataItem[key]) === 1);

    return isMandatory.length == 1;
  },
  params: ['data', 'key'],
};

const cpf = {
  validate(value) {
    const cpf = String(getOnlyNumbersFromString(value));

    let numeros, digitos, soma, i, resultado, digitos_iguais;
    digitos_iguais = 1;
    if (cpf.length < 11) return false;
    for (i = 0; i < cpf.length - 1; i++)
      if (cpf.charAt(i) != cpf.charAt(i + 1)) {
        digitos_iguais = 0;
        break;
      }
    if (!digitos_iguais) {
      numeros = cpf.substring(0, 9);
      digitos = cpf.substring(9);
      soma = 0;
      for (i = 10; i > 1; i--) soma += numeros.charAt(10 - i) * i;
      resultado = soma % 11 < 2 ? 0 : 11 - (soma % 11);
      if (resultado != digitos.charAt(0)) return false;
      numeros = cpf.substring(0, 10);
      soma = 0;
      for (i = 11; i > 1; i--) soma += numeros.charAt(11 - i) * i;
      resultado = soma % 11 < 2 ? 0 : 11 - (soma % 11);
      if (resultado != digitos.charAt(1)) return false;
      return true;
    } else return false;
  },
};

const cnpj = {
  validate(value) {
    value = String(getOnlyNumbersFromString(value));

    let numeros, digitos, soma, i, resultado, pos, tamanho, digitos_iguais;
    if (value.length == 0) {
      return false;
    }

    value = value.replace(/\D+/g, '');
    digitos_iguais = 1;

    for (i = 0; i < value.length - 1; i++)
      if (value.charAt(i) != value.charAt(i + 1)) {
        digitos_iguais = 0;
        break;
      }
    if (digitos_iguais) return false;

    tamanho = value.length - 2;
    numeros = value.substring(0, tamanho);
    digitos = value.substring(tamanho);
    soma = 0;
    pos = tamanho - 7;
    for (i = tamanho; i >= 1; i--) {
      soma += numeros.charAt(tamanho - i) * pos--;
      if (pos < 2) pos = 9;
    }
    resultado = soma % 11 < 2 ? 0 : 11 - (soma % 11);
    if (resultado != digitos.charAt(0)) {
      return false;
    }
    tamanho = tamanho + 1;
    numeros = value.substring(0, tamanho);
    soma = 0;
    pos = tamanho - 7;
    for (i = tamanho; i >= 1; i--) {
      soma += numeros.charAt(tamanho - i) * pos--;
      if (pos < 2) pos = 9;
    }

    resultado = soma % 11 < 2 ? 0 : 11 - (soma % 11);

    return resultado == digitos.charAt(1);
  },
};

const telephone = {
  validate(value) {
    return /^(|\([0-9]{2}\)[\s][0-9]{4}-[0-9]{4})$/.test(value);
  },
};

const cellphone = {
  validate(value) {
    return /^(|\([0-9]{2}\)[\s][0-9]{4,5}-[0-9]{4})$/.test(value);
  },
};

const withoutDot = {
  validate(value) {
    return /^[^.]*$/.test(value);
  },
};

const date = {
  validate(value) {
    if (/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/.test(value)) {
      const parsedDate = parse(value, 'dd/MM/yyyy', new Date());
      const result = isValid(parsedDate);

      return result;
    }
    return;
  },
};

const date_bigger_than_today = {
  validate(value) {
    const [day, month, year] = value.split('/');
    const date = new Date(Number(year), Number(month) - 1, Number(day));
    const today = new Date();

    return today.getTime() >= date.getTime();
  },
};

let dynamicMessage = 'Existem erros nos campos!';
const handlerValidation = {
  validate(_, { valid, message }) {
    dynamicMessage = message || dynamicMessage;
    return typeof valid == 'undefined' ? [] : valid;
  },
  params: ['valid', 'message'],
  message() {
    return dynamicMessage;
  },
};

const validations = {
  required,
  numeric,
  email,
  max,
  min,
  max_value,
  min_value,
  cep,
  minmax_number,
  target_bigger_than_reference,
  cpf,
  cnpj,
  telephone,
  cellphone,
  withoutDot,
  target_is_duplicated,
  date,
  date_bigger_than_today,
  target_is_mandatory,
  handlerValidation,
};

// para testar as validações do php descomentar as linhas de baixo
//for (const key in validations) {
//validations[key] = { validate: () => true, params: []};
//}

export default validations;
