import { ElMessage } from 'element-plus';
import { watch, nextTick } from 'vue';

const TRIGGER_INPUT = "change";
const TRIGGER_BLUR = "blur";
function useFormRulePresets() {
  const required = (label = "\u6B64\u9879", trigger = TRIGGER_BLUR) => ({
    required: true,
    message: `${label}\u4E3A\u5FC5\u586B\u9879`,
    trigger
  });
  const requiredIf = (required2, label = "\u6B64\u9879", trigger = TRIGGER_BLUR) => ({
    required: required2 != null ? required2 : false,
    message: `${label}\u4E3A\u5FC5\u586B\u9879`,
    trigger
  });
  const validatorIf = (shouldError, formRef, label = "\u6B64\u9879") => {
    let field = "";
    watch(
      () => shouldError(),
      () => nextTick(() => {
        var _a;
        return (_a = formRef == null ? void 0 : formRef.value) == null ? void 0 : _a.validateField(field).catch(() => {
        });
      }),
      { immediate: false, deep: true }
    );
    return {
      validator: (_, __, callback) => {
        field = _.field;
        if (shouldError()) {
          callback(new Error(`${label}\u4E3A\u5FC5\u586B`));
        } else {
          callback();
        }
      },
      trigger: ["blur", "change"]
    };
  };
  const maxLen = (len, label = "\u6B64\u9879", trigger = TRIGGER_INPUT) => ({
    max: len,
    message: `${label}\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7 ${len} \u4E2A\u5B57\u7B26`,
    trigger
  });
  const minLen = (len, label = "\u6B64\u9879", trigger = TRIGGER_INPUT) => ({
    min: len,
    message: `${label}\u957F\u5EA6\u4E0D\u80FD\u5C11\u4E8E ${len} \u4E2A\u5B57\u7B26`,
    trigger
  });
  const pattern = (re, msg, trigger = TRIGGER_BLUR) => ({
    pattern: re,
    message: msg,
    trigger
  });
  const validator = (fn, trigger = TRIGGER_BLUR) => ({
    trigger,
    validator: (_rule, value, callback) => {
      Promise.resolve(fn(value)).then((res) => {
        if (res === true) return callback();
        return callback(new Error(res));
      }).catch((err) => callback(err instanceof Error ? err : new Error(String(err))));
    }
  });
  const phone = () => pattern(/^(1[3-9]\d{9})$|^(0\d{2,3}[-]?\d{7,8})$|^(\(\d{3,4}\)\d{7,8})$|^(\d{7,})$/, "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u624B\u673A\u53F7\u6216\u7535\u8BDD\u53F7");
  const idCard = () => validator((value) => {
    if (!value) return true;
    const idCard2 = String(value).trim();
    if (idCard2.length === 15) {
      const reg15 = /^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
      if (!reg15.test(idCard2)) {
        return "\u8BF7\u8F93\u5165\u6709\u6548\u768415\u4F4D\u8EAB\u4EFD\u8BC1\u53F7";
      }
      return true;
    }
    if (idCard2.length === 18) {
      const reg18 = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}(\d|X|x)$/;
      if (!reg18.test(idCard2)) {
        return "\u8BF7\u8F93\u5165\u6709\u6548\u768418\u4F4D\u8EAB\u4EFD\u8BC1\u53F7";
      }
      const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
      const parity = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
      let sum = 0;
      let ai = 0;
      let wi = 0;
      for (let i = 0; i < 17; i++) {
        ai = parseInt(idCard2[i]);
        wi = factor[i];
        sum += ai * wi;
      }
      const last = parity[sum % 11];
      if (last !== idCard2[17].toUpperCase()) {
        return "\u8EAB\u4EFD\u8BC1\u53F7\u6821\u9A8C\u7801\u9519\u8BEF";
      }
      return true;
    }
    return "\u8EAB\u4EFD\u8BC1\u53F7\u5FC5\u987B\u662F15\u4F4D\u621618\u4F4D";
  }, TRIGGER_BLUR);
  const email = () => pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740");
  const digits = (label = "\u6B64\u9879", trigger = TRIGGER_INPUT) => pattern(/^\d+$/, `${label}\u9700\u4E3A\u7EAF\u6570\u5B57`, trigger);
  const intRange = (min, max, label = "\u6570\u503C") => validator((v) => {
    if (v === "" || v === void 0 || v === null) return `\u8BF7\u8F93\u5165${label}`;
    if (!Number.isInteger(Number(v))) return `${label}\u9700\u4E3A\u6574\u6570`;
    const n = Number(v);
    if (n < min || n > max) return `${label}\u9700\u5728 ${min}~${max} \u4E4B\u95F4`;
    return true;
  }, TRIGGER_INPUT);
  const confirmSame = (getOther, label = "\u4E24\u6B21\u8F93\u5165") => validator((v) => v === getOther() ? true : `${label}\u4E0D\u4E00\u81F4`, TRIGGER_INPUT);
  const toDate = (v) => {
    if (v instanceof Date && !isNaN(v.getTime())) return v;
    if (typeof v === "number") {
      const d = new Date(v);
      return isNaN(d.getTime()) ? null : d;
    }
    if (typeof v === "string" && v) {
      const d = new Date(v);
      return isNaN(d.getTime()) ? null : d;
    }
    return null;
  };
  const dateAfterToday = (label = "\u65E5\u671F", trigger = TRIGGER_INPUT) => validator((v) => {
    if (v === "" || v === void 0 || v === null) return true;
    const d = toDate(v);
    if (!d) return `\u8BF7\u9009\u62E9\u6709\u6548\u7684${label}`;
    const today = /* @__PURE__ */ new Date();
    today.setHours(0, 0, 0, 0);
    return d.getTime() > today.getTime() ? true : `${label}\u5FC5\u987B\u5728\u4ECA\u5929\u4E4B\u540E`;
  }, trigger);
  const dateBeforeToday = (label = "\u65E5\u671F", trigger = TRIGGER_INPUT) => validator((v) => {
    if (v === "" || v === void 0 || v === null) return true;
    const d = toDate(v);
    if (!d) return `\u8BF7\u9009\u62E9\u6709\u6548\u7684${label}`;
    const today = /* @__PURE__ */ new Date();
    today.setHours(0, 0, 0, 0);
    return d.getTime() < today.getTime() ? true : `${label}\u5FC5\u987B\u5728\u4ECA\u5929\u4E4B\u524D`;
  }, trigger);
  const numberPrecision = (maxIntDigits, maxFracDigits, label = "\u6B64\u9879") => validator((v) => {
    if (v === "" || v === void 0 || v === null) return true;
    const str = String(v).trim();
    if (!/^\d+(?:\.\d+)?$/.test(str)) {
      return `${label}\u5FC5\u987B\u4E3A\u6570\u5B57`;
    }
    const [intPart, fracPart = ""] = str.split(".");
    if (maxIntDigits !== null) {
      if (intPart.length > maxIntDigits) {
        return `${label}\u6574\u6570\u4F4D\u4E0D\u80FD\u8D85\u8FC7${maxIntDigits}\u4F4D`;
      }
    }
    if (fracPart && maxFracDigits !== null && fracPart.length > maxFracDigits) {
      if (maxFracDigits === 0) {
        return `${label}\u5FC5\u987B\u4E3A\u6574\u6570`;
      }
      return `${label}\u5C0F\u6570\u4F4D\u4E0D\u80FD\u8D85\u8FC7${maxFracDigits}\u4F4D`;
    }
    return true;
  }, TRIGGER_BLUR);
  const validateLength = (value, maxLength, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    if (String(value).length > maxLength) {
      ElMessage.error(`${fieldName}\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7${maxLength}\u4E2A\u5B57\u7B26`);
      return false;
    }
    return true;
  };
  const validateRequired = (value, fieldName = "\u5B57\u6BB5") => {
    if (!value || String(value).trim() === "") {
      ElMessage.error(`${fieldName}\u4E0D\u80FD\u4E3A\u7A7A`);
      return false;
    }
    return true;
  };
  const validateNumber = (value, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    if (!/^\d+$/.test(String(value))) {
      ElMessage.error(`${fieldName}\u5FC5\u987B\u4E3A\u7EAF\u6570\u5B57`);
      return false;
    }
    return true;
  };
  const validateIntRange = (value, min, max, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    const num = Number(value);
    if (!Number.isInteger(num)) {
      ElMessage.error(`${fieldName}\u5FC5\u987B\u4E3A\u6574\u6570`);
      return false;
    }
    if (num < min || num > max) {
      ElMessage.error(`${fieldName}\u5FC5\u987B\u5728${min}~${max}\u4E4B\u95F4`);
      return false;
    }
    return true;
  };
  const validateChinese = (value, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    if (!/^[\u4e00-\u9fa5]+$/.test(String(value))) {
      ElMessage.error(`${fieldName}\u5FC5\u987B\u4E3A\u4E2D\u6587`);
      return false;
    }
    return true;
  };
  const validateEmail = (value, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value))) {
      ElMessage.error(`${fieldName}\u683C\u5F0F\u4E0D\u6B63\u786E`);
      return false;
    }
    return true;
  };
  const validatePhone = (value, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    if (!/^1[3-9]\d{9}$/.test(String(value))) {
      ElMessage.error(`${fieldName}\u683C\u5F0F\u4E0D\u6B63\u786E`);
      return false;
    }
    return true;
  };
  const validateIdCard = (value, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    const idCard2 = String(value).trim();
    if (idCard2.length === 15) {
      const reg15 = /^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
      if (!reg15.test(idCard2)) {
        ElMessage.error(`${fieldName}\u683C\u5F0F\u4E0D\u6B63\u786E`);
        return false;
      }
      return true;
    }
    if (idCard2.length === 18) {
      const reg18 = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}(\d|X|x)$/;
      if (!reg18.test(idCard2)) {
        ElMessage.error(`${fieldName}\u683C\u5F0F\u4E0D\u6B63\u786E`);
        return false;
      }
      const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
      const parity = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
      let sum = 0;
      for (let i = 0; i < 17; i++) {
        sum += parseInt(idCard2[i]) * factor[i];
      }
      const last = parity[sum % 11];
      if (last !== idCard2[17].toUpperCase()) {
        ElMessage.error(`${fieldName}\u6821\u9A8C\u7801\u9519\u8BEF`);
        return false;
      }
      return true;
    }
    ElMessage.error(`${fieldName}\u5FC5\u987B\u662F15\u4F4D\u621618\u4F4D`);
    return false;
  };
  const validatePattern = (value, pattern2, message) => {
    if (!value) return true;
    if (!pattern2.test(String(value))) {
      ElMessage.error(message);
      return false;
    }
    return true;
  };
  const validateMultiple = (value, validators) => {
    for (const validator2 of validators) {
      if (!validator2(value)) {
        return false;
      }
    }
    return true;
  };
  const validateDecimalPrecision = (value, maxIntDigits, maxFracDigits, fieldName = "\u5B57\u6BB5") => {
    if (!value) return true;
    const str = String(value).trim();
    if (!/^\d+(?:\.\d+)?$/.test(str)) {
      ElMessage.error(`${fieldName}\u5FC5\u987B\u4E3A\u6570\u5B57`);
      return false;
    }
    const [intPart, fracPart = ""] = str.split(".");
    if (intPart.length > maxIntDigits) {
      ElMessage.error(`${fieldName}\u6574\u6570\u4F4D\u4E0D\u80FD\u8D85\u8FC7${maxIntDigits}\u4F4D`);
      return false;
    }
    if (fracPart && fracPart.length > maxFracDigits) {
      if (maxFracDigits === 0) {
        ElMessage.error(`${fieldName}\u5FC5\u987B\u4E3A\u6574\u6570`);
        return false;
      }
      ElMessage.error(`${fieldName}\u5C0F\u6570\u4F4D\u4E0D\u80FD\u8D85\u8FC7${maxFracDigits}\u4F4D`);
      return false;
    }
    return true;
  };
  const validateField = (value, type, fieldName, options) => {
    switch (type) {
      case "required":
        return validateRequired(value, fieldName);
      case "length":
        return validateLength(value, options.maxLength, fieldName);
      case "number":
        return validateNumber(value, fieldName);
      case "range":
        return validateIntRange(value, options.min, options.max, fieldName);
      case "chinese":
        return validateChinese(value, fieldName);
      case "email":
        return validateEmail(value, fieldName);
      case "phone":
        return validatePhone(value, fieldName);
      case "idcard":
        return validateIdCard(value, fieldName);
      case "pattern":
        return validatePattern(value, options.pattern, options.message);
      case "decimal":
        return validateDecimalPrecision(value, options.maxIntDigits, options.maxFracDigits, fieldName);
      default:
        return true;
    }
  };
  return {
    required,
    requiredIf,
    validatorIf,
    maxLen,
    minLen,
    pattern,
    validator,
    phone,
    idCard,
    email,
    digits,
    intRange,
    confirmSame,
    dateAfterToday,
    dateBeforeToday,
    numberPrecision,
    validateRequired,
    validateNumber,
    validateIntRange,
    validateChinese,
    validateLength,
    validateEmail,
    validatePhone,
    validateIdCard,
    validatePattern,
    validateMultiple,
    validateField,
    validateDecimalPrecision
  };
}

export { useFormRulePresets };
