import { ref } from "vue";
import { isInteger, find } from "lodash-es";
import { Datetime } from "../../utils/datetime.js";
export function useRules() {
  const condition = (condition2, customError) => condition2 || customError;
  const require = (customError = "This field is required") => (value) => condition(!!value || value === false || value === 0, customError);
  const requireIf = (conditionIf, customError = "This field is required") => (value) => condition(!!value || value === false || value === 0 || !conditionIf, customError);
  const requireTrue = (customError = "This field must be true") => (value) => condition(!!value, customError);
  const requireTrueIf = (conditionIf, customError = "This field must be true") => (value) => condition(!!value || !conditionIf, customError);
  const requireNotEmpty = (customError = "This field is required") => (value) => condition(Array.isArray(value) ? value.length > 0 : !!value || value === false || value === 0, customError);
  const numeric = (customError = "This field must be a number") => (value) => condition(!value || !isNaN(Number(value)), customError);
  const range = (minValue, maxValue, customError = `Value is out of range (${minValue}-${maxValue})`) => (value) => condition(!value || value >= minValue && value <= maxValue, customError);
  const integer = (customError = "This field must be an integer") => (value) => condition(!value || isInteger(value) || /^\+?-?\d+$/.test(value), customError);
  const unique = (data, fieldName, customError = "This field must be unique") => (value) => condition(!value || !data || !find(data, [fieldName, value]), customError);
  const length = (length2, customError = `Length must be ${length2}`) => (value) => condition(!value || value.length == length2, customError);
  const lengthGreater = (length2, customError = `Length must be greater than ${length2}`) => (value) => condition(!value || value.length >= length2, customError);
  const lengthLess = (length2, customError = `Length must be less than ${length2}`) => (value) => condition(!value || value.length <= length2, customError);
  const telephone = (customError = "Invalid telephone number") => (value) => condition(!value || /^(?:\s*(?:\+66|0)\s?(?:[2-57](?:[\s-]?\d){7}|[689](?:[\s-]?\d){8})(?:#\d{1,5})?\s*(?:\([^()]+\)\s*)?(?:,(?=\s*\+?6?0)|,|$))*$/.test(value), customError);
  const telephoneSingle = (customError = "Invalid telephone number") => (value) => condition(!value || /^\s*(?:\+66|0)\s?(?:[2-57](?:[\s-]?\d){7}|[689](?:[\s-]?\d){8})(?:#\d{1,5})?\s*(?:\([^()]+\)\s*)?$/.test(value), customError);
  const internationalTelephone = (customError = "Invalid telephone number") => (value) => condition(!value || /^(?:\s*(?:\+?\d{1,3}[-\s]?)?(?:0?\d{1,4}[-\s]?)?\d{3,4}[-\s]?\d{3,4}(?:#\d{1,5})?\s*(?:\([^()]+\)\s*)?(?:,(?=\s*\+?\d)|,|$))*$/.test(value), customError);
  const internationalTelephoneSingle = (customError = "Invalid telephone number") => (value) => condition(!value || /^\s*(?:\+?\d{1,3}[-\s]?)?(?:0?\d{1,4}[-\s]?)?\d{3,4}[-\s]?\d{3,4}(?:#\d{1,5})?\s*(?:\([^()]+\)\s*)?$/.test(value), customError);
  const mobilePhone = (customError = "Invalid telephone number") => (value) => condition(!value || /^(?:\s*(?:\+66|0)\s?(?:6\d{8}|8\d{8}|9\d{8})\s*(?:,(?=\s*\+?6?0)|,|$))*$/.test(value), customError);
  const mobilePhoneSingle = (customError = "Invalid telephone number") => (value) => condition(!value || /^\s*(?:\+66|0)\s?(?:6\d{8}|8\d{8}|9\d{8})\s*$/.test(value), customError);
  const email = (customError = "Invalid email address") => (value) => condition(!value || /^([\w\-.]+)@([\w\-.]+)\.([a-z]{2,5})$/i.test(value), customError);
  const regex = (regex2, customError = "Invalid format") => (value) => condition(!value || new RegExp(regex2).test(value), customError);
  const idcard = (customError = "Invalid ID Card format") => (value) => condition(!value || /^\d{13}$/.test(value) && (11 - [...value].slice(0, 12).reduce((sum, n, i) => sum + +n * (13 - i), 0) % 11) % 10 === +value[12], customError);
  const DateFuture = (customError = "Date should be in the future") => (value) => condition(!value || Datetime().fromString(value).isFutureDate(), customError);
  const DatetimeFuture = (customError = "Datetime should be in the future") => (value) => condition(!value || Datetime().fromString(value).isFuture(), customError);
  const DateHappen = (customError = "Date should be already happened") => (value) => condition(!value || Datetime().fromString(value).isHappenDate(), customError);
  const DatetimeHappen = (customError = "Date should be already happened") => (value) => condition(!value || Datetime().fromString(value).isHappen(), customError);
  const DateAfter = (compareDate, customError) => (value) => condition(!value || Datetime().fromString(value).isAfter(compareDate), customError || "Date should be after " + compareDate);
  const DateBefore = (compareDate, customError) => (value) => condition(!value || Datetime().fromString(value).isBefore(compareDate), customError || "Date should be before " + compareDate);
  const DateEqual = (compareDate, customError) => (value) => condition(!value || Datetime().fromString(value).isEqual(compareDate), customError || "Date should be equal to " + compareDate);
  const rules = ref({
    require,
    requireIf,
    requireTrue,
    requireTrueIf,
    requireNotEmpty,
    numeric,
    range,
    integer,
    unique,
    length,
    lengthGreater,
    lengthLess,
    telephone,
    telephoneSingle,
    internationalTelephone,
    internationalTelephoneSingle,
    mobilePhone,
    mobilePhoneSingle,
    email,
    regex,
    idcard,
    DateFuture,
    DatetimeFuture,
    DateHappen,
    DatetimeHappen,
    DateAfter,
    DateBefore,
    DateEqual
  });
  return { rules, ...rules.value };
}
