// ? Element 常用表单校验规则

/**
 *  @rule 手机号
 */
export function checkPhoneNumber(rule: any, value: any, callback: any) {
  const regexp = /^(((13[0-9]{1})|(15[0-9]{1})|(16[0-9]{1})|(17[3-8]{1})|(18[0-9]{1})|(19[0-9]{1})|(14[5-7]{1}))+\d{8})$/;
  if (value === "") callback("请输入手机号码");
  if (!regexp.test(value)) {
    callback(new Error("请输入正确的手机号码"));
  } else {
    return callback();
  }
}

/**
 * 自定义校验函数：检查是否全是空格或为空
 */
export function validateNoEmptySpaces(rule: any, value: any, callback: any) {
  // 如果值为空或者去空格后为空字符串，则报错
  if (value === null || value === undefined || value.trim() === "") {
    callback(new Error("内容不能全为空格"));
  } else {
    callback(); // 校验通过
  }
}

/**
 * 验证正整数
 * @param errorMessage - 错误提示信息，默认为"必须为正整数"
 * @param options - 配置选项
 * @param options.required - 是否必填，默认为true
 * @param options.checkLeadingZero - 是否检查前导零，默认为true（用于字符串输入）
 * @returns 验证函数
 */
export function validatePositiveInteger(
  errorMessage: string = "必须为正整数",
  options: { required?: boolean; checkLeadingZero?: boolean } = {}
) {
  const { required = true, checkLeadingZero = true } = options;

  return (rule: any, value: any, callback: any) => {
    // 检查是否为空
    if (value === null || value === undefined || value === "") {
      if (required) {
        callback(new Error(errorMessage));
        return;
      } else {
        callback();
        return;
      }
    }

    // 对于数字类型（如 el-input-number），直接验证数字
    if (typeof value === "number") {
      if (value <= 0 || !Number.isInteger(value)) {
        callback(new Error(errorMessage));
        return;
      }
      callback();
      return;
    }

    // 转换为字符串进行检查
    const strValue = value.toString().trim();
    if (strValue === "") {
      if (required) {
        callback(new Error(errorMessage));
        return;
      } else {
        callback();
        return;
      }
    }

    // 检查是否有前导零（除了单独的"0"）
    if (checkLeadingZero && strValue.length > 1 && strValue.startsWith("0")) {
      callback(new Error(errorMessage));
      return;
    }

    // 检查是否为数字
    const num = Number(strValue);
    if (isNaN(num)) {
      callback(new Error(errorMessage));
      return;
    }

    // 检查是否为正数
    if (num <= 0) {
      callback(new Error(errorMessage));
      return;
    }

    // 检查是否为整数
    if (!Number.isInteger(num)) {
      callback(new Error(errorMessage));
      return;
    }

    callback();
  };
}

/**
 * 验证正数（可以是小数）
 * @param errorMessage - 错误提示信息，默认为"必须为正数"
 * @returns 验证函数
 */
export function validatePositiveNumber(errorMessage: string = "必须为正数") {
  return (rule: any, value: any, callback: any) => {
    if (value === undefined || value === null || value.toString().trim() === "") {
      callback();
      return;
    }
    const num = Number(value);
    if (isNaN(num) || num <= 0) {
      callback(new Error(errorMessage));
      return;
    }
    callback();
  };
}

/**
 * 验证密码（6-16位，必须包含字母和数字）
 */
export function validatePassword(rule: any, value: string, callback: any) {
  if (!value) {
    callback(new Error("请输入密码"));
    return;
  }
  if (value.length < 6 || value.length > 16) {
    callback(new Error("密码长度为6-16位，密码必须包含字母和数字"));
    return;
  }
  if (!/^(?=.*[a-zA-Z])(?=.*\d).+$/.test(value)) {
    callback(new Error("密码长度为6-16位，密码必须包含字母和数字"));
    return;
  }
  callback();
}

/**
 * 验证确认密码（两次输入的密码必须一致）
 * @param originalPassword - 原始密码值或获取原始密码的函数
 * @param errorMessage - 错误提示信息，默认为"两次输入的密码不一致"
 * @returns 验证函数
 */
export function validateConfirmPassword(
  originalPassword: string | (() => string),
  errorMessage: string = "两次输入的密码不一致"
) {
  return (rule: any, value: string, callback: any) => {
    if (!value) {
      callback(new Error("请确认密码"));
      return;
    }
    const original = typeof originalPassword === "function" ? originalPassword() : originalPassword;
    if (value !== original) {
      callback(new Error(errorMessage));
      return;
    }
    callback();
  };
}

/**
 * 验证日期不能早于今天
 * @param errorMessage - 错误提示信息，默认为"日期不能早于当前时间"
 * @returns 验证函数
 */
export function validateDateNotBeforeToday(errorMessage: string = "日期不能早于当前时间") {
  return (rule: any, value: any, callback: any) => {
    if (!value) {
      callback();
      return;
    }
    const selectedDate = new Date(value);
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    if (selectedDate < today) {
      callback(new Error(errorMessage));
      return;
    }
    callback();
  };
}

/**
 * 验证日期范围（开始时间必须早于结束时间）
 * @param getStartDate - 获取开始日期的函数
 * @param getEndDate - 获取结束日期的函数（可选，如果不提供则使用当前值作为结束日期）
 * @param startErrorMessage - 开始日期错误提示，默认为"开始时间不能早于当前时间"
 * @param endErrorMessage - 结束日期错误提示，默认为"结束时间不能早于当前时间"
 * @param rangeErrorMessage - 日期范围错误提示，默认为"开始时间必须早于结束时间"
 * @param checkToday - 是否检查不能早于今天，默认为true
 * @returns 验证函数
 */
export function validateDateRange(
  getStartDate: () => any,
  getEndDate?: () => any,
  startErrorMessage: string = "开始时间不能早于当前时间",
  endErrorMessage: string = "结束时间不能早于当前时间",
  rangeErrorMessage: string = "开始时间必须早于结束时间",
  checkToday: boolean = true,
  allowSameDay: boolean = false
) {
  return (rule: any, value: any, callback: any) => {
    if (!value) {
      callback();
      return;
    }
    const selectedDate = new Date(value);
    selectedDate.setHours(0, 0, 0, 0);

    // 自动判断是开始日期还是结束日期
    // 优先通过值比较判断（最可靠），其次通过字段名判断
    const startDateValue = getStartDate();
    const endDateValue = getEndDate ? getEndDate() : null;
    const fieldName = rule?.field || "";

    let isStartDate = false;

    // 优先通过值比较判断
    if (value === startDateValue) {
      isStartDate = true;
    } else if (endDateValue && value === endDateValue) {
      isStartDate = false;
    } else if (fieldName) {
      // 如果值比较无法判断，则通过字段名判断
      // 如果字段名包含 "begin"、"start"、"开始" 等关键词，认为是开始日期
      const lowerFieldName = fieldName.toLowerCase();
      isStartDate = lowerFieldName.includes("begin") || lowerFieldName.includes("start") || lowerFieldName.includes("开始");
      // 如果字段名包含 "end"、"结束" 等关键词，明确认为是结束日期
      if (lowerFieldName.includes("end") || lowerFieldName.includes("结束")) {
        isStartDate = false;
      }
    }

    // 验证不能早于今天
    if (checkToday) {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      if (selectedDate < today) {
        callback(new Error(isStartDate ? startErrorMessage : endErrorMessage));
        return;
      }
    }

    // 验证日期范围
    if (isStartDate && getEndDate) {
      // 验证开始日期：开始日期必须早于结束日期
      const endDate = getEndDate();
      if (endDate) {
        const end = new Date(endDate);
        end.setHours(0, 0, 0, 0);
        const isInvalid = allowSameDay ? selectedDate > end : selectedDate >= end;
        if (isInvalid) {
          callback(new Error(rangeErrorMessage));
          return;
        }
      }
    } else if (!isStartDate && getStartDate) {
      // 验证结束日期：结束日期必须晚于开始日期
      const startDate = getStartDate();
      if (startDate) {
        const start = new Date(startDate);
        start.setHours(0, 0, 0, 0);
        const isInvalid = allowSameDay ? selectedDate < start : selectedDate <= start;
        if (isInvalid) {
          callback(new Error(rangeErrorMessage));
          return;
        }
      }
    }

    callback();
  };
}

/**
 * 验证正整数（简化版，用于库存、数量等字段，允许空值）
 * @param errorMessage - 错误提示信息，默认为"必须为正整数"
 * @returns 验证函数
 * @deprecated 请使用 validatePositiveInteger(errorMessage, { required: false })
 */
export function validatePositiveIntegerOptional(errorMessage: string = "必须为正整数") {
  return validatePositiveInteger(errorMessage, { required: false, checkLeadingZero: true });
}

/**
 * 验证日期范围（开始时间必须早于结束时间，且不能早于今天）
 * @param getStartDate - 获取开始日期的函数
 * @param getEndDate - 获取结束日期的函数（可选，如果不提供则使用当前值作为结束日期）
 * @param startErrorMessage - 开始日期错误提示，默认为"开始时间不能早于当前时间"
 * @param endErrorMessage - 结束日期错误提示，默认为"结束时间不能早于当前时间"
 * @param rangeErrorMessage - 日期范围错误提示，默认为"开始时间必须早于结束时间"
 * @returns 验证函数
 * @deprecated 请使用 validateDateRange(..., true) 或 validateDateRange(..., checkToday: true)
 */
export function validateDateRangeWithToday(
  getStartDate: () => any,
  getEndDate?: () => any,
  startErrorMessage: string = "开始时间不能早于当前时间",
  endErrorMessage: string = "结束时间不能早于当前时间",
  rangeErrorMessage: string = "开始时间必须早于结束时间"
) {
  return validateDateRange(getStartDate, getEndDate, startErrorMessage, endErrorMessage, rangeErrorMessage, true);
}

/**
 * 验证日期范围数组（每个日期范围的开始时间必须早于结束时间）
 * @param errorMessage - 错误提示信息，默认为"开始时间必须早于结束时间"
 * @param checkToday - 是否检查不能早于今天，默认为false
 * @param todayErrorMessage - 今天错误提示，默认为"时间不能早于当前时间"
 * @returns 验证函数
 */
export function validateDateRangeArray(
  errorMessage: string = "开始时间必须早于结束时间",
  checkToday: boolean = false,
  todayErrorMessage: string = "时间不能早于当前时间"
) {
  return (rule: any, value: any, callback: any) => {
    if (!value || value.length === 0) {
      callback();
      return;
    }
    if (!Array.isArray(value) || value.length !== 2) {
      callback(new Error("请选择完整的日期范围"));
      return;
    }

    const startDate = new Date(value[0]);
    const endDate = new Date(value[1]);

    // 验证不能早于今天
    if (checkToday) {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      if (startDate < today) {
        callback(new Error("开始" + todayErrorMessage));
        return;
      }
      if (endDate < today) {
        callback(new Error("结束" + todayErrorMessage));
        return;
      }
    }

    // 验证开始时间必须早于结束时间
    if (startDate >= endDate) {
      callback(new Error(errorMessage));
      return;
    }
    callback();
  };
}

/**
 * 验证日期范围数组（带今天检查）
 * @param checkToday - 是否检查不能早于今天，默认为true
 * @param rangeErrorMessage - 日期范围错误提示，默认为"开始时间必须早于结束时间"
 * @param todayErrorMessage - 今天错误提示，默认为"时间不能早于当前时间"
 * @returns 验证函数
 * @deprecated 请使用 validateDateRangeArray(rangeErrorMessage, checkToday, todayErrorMessage)
 */
export function validateDateRangeArrayWithToday(
  checkToday: boolean = true,
  rangeErrorMessage: string = "开始时间必须早于结束时间",
  todayErrorMessage: string = "时间不能早于当前时间"
) {
  return validateDateRangeArray(rangeErrorMessage, checkToday, todayErrorMessage);
}

/**
 * 条件必填验证（根据某个条件判断是否必填）
 * @param condition - 判断条件的函数，返回true表示必填
 * @param errorMessage - 错误提示信息
 * @returns 验证函数
 */
export function validateConditionalRequired(condition: () => boolean, errorMessage: string) {
  return (rule: any, value: any, callback: any) => {
    if (condition()) {
      if (!value || (Array.isArray(value) && value.length === 0) || (typeof value === "string" && value.trim() === "")) {
        callback(new Error(errorMessage));
        return;
      }
    }
    callback();
  };
}

/**
 * 验证数组最小长度
 * @param minLength - 最小长度
 * @param errorMessage - 错误提示信息
 * @returns 验证函数
 */
export function validateArrayMinLength(minLength: number, errorMessage: string) {
  return (rule: any, value: any, callback: any) => {
    if (!value || !Array.isArray(value) || value.length < minLength) {
      callback(new Error(errorMessage));
      return;
    }
    callback();
  };
}

/**
 * 验证日期数组列表（每个日期项的开始时间必须早于结束时间）
 * @param getDateList - 获取日期列表的函数
 * @param itemErrorMessage - 单个日期项错误提示，默认为"日期项未完整填写"
 * @param rangeErrorMessage - 日期范围错误提示，默认为"开始时间必须早于结束时间"
 * @param checkToday - 是否检查不能早于今天，默认为false
 * @returns 验证函数
 */
export function validateDateListArray(
  getDateList: () => any[],
  itemErrorMessage: string = "日期项未完整填写",
  rangeErrorMessage: string = "开始时间必须早于结束时间",
  checkToday: boolean = false
) {
  return (rule: any, value: any, callback: any) => {
    const dateList = getDateList();
    if (!dateList || dateList.length === 0) {
      callback();
      return;
    }

    const today = new Date();
    today.setHours(0, 0, 0, 0);

    for (let i = 0; i < dateList.length; i++) {
      const dateItem = dateList[i];
      if (!dateItem || !Array.isArray(dateItem) || dateItem.length !== 2) {
        callback(new Error(`第${i + 1}个${itemErrorMessage}`));
        return;
      }

      const startDate = new Date(dateItem[0]);
      const endDate = new Date(dateItem[1]);

      // 验证不能早于今天
      if (checkToday) {
        if (startDate < today) {
          callback(new Error(`第${i + 1}个日期项的开始时间不能早于当前时间`));
          return;
        }
        if (endDate < today) {
          callback(new Error(`第${i + 1}个日期项的结束时间不能早于当前时间`));
          return;
        }
      }

      // 验证开始时间必须早于结束时间
      if (startDate >= endDate) {
        callback(new Error(`第${i + 1}个日期项的${rangeErrorMessage}`));
        return;
      }
    }

    callback();
  };
}

/**
 * 验证正整数（用于 el-input-number，value 已经是数字类型）
 * @param errorMessage - 错误提示信息，默认为"必须为正整数"
 * @returns 验证函数
 * @deprecated 请使用 validatePositiveInteger(errorMessage, { required: false, checkLeadingZero: false })
 */
export function validatePositiveIntegerForNumber(errorMessage: string = "必须为正整数") {
  return validatePositiveInteger(errorMessage, { required: false, checkLeadingZero: false });
}

/**
 * 验证价格格式（整数部分最多6位，小数部分最多2位）
 * @param errorMessage - 错误提示信息，默认为"整数部分最多6位，小数部分最多2位"
 * @returns 验证函数
 */
export function validatePriceFormat(errorMessage: string = "整数部分最多6位，小数部分最多2位") {
  return (rule: any, value: any, callback: any) => {
    if (!value || value.toString().trim() === "") {
      callback();
      return;
    }
    const strValue = value.toString().trim();
    // 验证格式：整数部分最多6位，小数部分最多2位
    const regex = /^\d{1,6}(\.\d{1,2})?$/;
    if (!regex.test(strValue)) {
      callback(new Error(errorMessage));
      return;
    }
    callback();
  };
}

/**
 * 验证价格比较（第一个价格必须大于等于第二个价格）
 * @param getFirstPrice - 获取第一个价格的函数（通常是抵扣价格）
 * @param getSecondPrice - 获取第二个价格的函数（通常是售卖价格）
 * @param errorMessage - 错误提示信息，默认为"抵扣价格不能低于售卖价格"
 * @returns 验证函数
 */
export function validatePriceComparison(
  getFirstPrice: () => any,
  getSecondPrice: () => any,
  errorMessage: string = "抵扣价格不能低于售卖价格"
) {
  return (rule: any, value: any, callback: any) => {
    const firstPrice = getFirstPrice();
    const secondPrice = getSecondPrice();

    // 如果任一价格为空，不进行验证
    if (!firstPrice || !secondPrice || firstPrice.toString().trim() === "" || secondPrice.toString().trim() === "") {
      callback();
      return;
    }

    const firstNum = Number(firstPrice);
    const secondNum = Number(secondPrice);

    // 如果转换失败，不进行验证（由其他验证规则处理）
    if (isNaN(firstNum) || isNaN(secondNum)) {
      callback();
      return;
    }

    // 验证第一个价格必须大于等于第二个价格
    if (firstNum < secondNum) {
      callback(new Error(errorMessage));
      return;
    }

    callback();
  };
}
