/**
 * 路径匹配器
 * @param {string} pattern
 * @param {string} path
 * @returns {Boolean}
 */
export function isPathMatch(pattern, path) {
  const regexPattern = pattern
    .replace(/\//g, '\\/')
    .replace(/\*\*/g, '.*')
    .replace(/\*/g, '[^\\/]*')
  const regex = new RegExp(`^${regexPattern}$`)
  return regex.test(path)
}

/**
 * 判断value字符串是否为空
 * @param {string} value
 * @returns {Boolean}
 */
export function isEmpty(value) {
  if (value == null || value == '' || value == undefined || value == 'undefined') {
    return true
  }
  return false
}

/**
 * 判断url是否是http或https
 * @param {string} url
 * @returns {Boolean}
 */
export function isHttp(url) {
  return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
}

/**
 * 判断path是否为外链
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal(path) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

/**
 * @param {string} str
 * @returns {Boolean}
 */
export function validUsername(str) {
  const valid_map = ['admin', 'editor']
  return valid_map.indexOf(str.trim()) >= 0
}

/**
 * @param {string} url
 * @returns {Boolean}
 */
export function validURL(url) {
  const reg =
    /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return reg.test(url)
}

/**
 * @param {string} str
 * @returns {Boolean}
 */
export function validLowerCase(str) {
  const reg = /^[a-z]+$/
  return reg.test(str)
}

/**
 * @param {string} str
 * @returns {Boolean}
 */
export function validUpperCase(str) {
  const reg = /^[A-Z]+$/
  return reg.test(str)
}

/**
 * @param {string} str
 * @returns {Boolean}
 */
export function validAlphabets(str) {
  const reg = /^[A-Za-z]+$/
  return reg.test(str)
}

/**
 * @param {string} email
 * @returns {Boolean}
 */
export function validEmail(email) {
  const reg =
    /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
  return reg.test(email)
}

/**
 * @param {string} str
 * @returns {Boolean}
 */
export function isString(str) {
  return typeof str === 'string' || str instanceof String
}

/**
 * @param {Array} arg
 * @returns {Boolean}
 */
export function isArray(arg) {
  if (typeof Array.isArray === 'undefined') {
    return Object.prototype.toString.call(arg) === '[object Array]'
  }
  return Array.isArray(arg)
}
/**
 * 英文姓名校验规则
 */
export const validateEnglish = (rule, value, callback) => {
  // if (!value) {
  //   // 如果值为空且字段不是必填的，直接通过校验
  //   return callback()
  // }

  // 1. 基本字符检查
  if (!/^[A-Za-z\s\-'.]+$/.test(value)) {
    return callback(new Error("包含非法字符，只允许英文字母、空格、-、'和."))
  }

  // 2. 首字母大写检查
  // if (!/^[A-Z]/.test(value)) {
  //   return callback(new Error('名字应以大写字母开头'))
  // }

  // 3. 长度检查
  if (value.length < 2) {
    return callback(new Error('名字至少需要2个字符'))
  }

  // 4. 连续特殊字符检查
  if (/[\s\-'.]{2,}/.test(value)) {
    return callback(new Error('不能连续使用特殊字符'))
  }

  // 5. 开头或结尾不能是特殊字符
  if (/^[\s\-'.]|[\s\-'.]$/.test(value.trim())) {
    return callback(new Error('名字不能以特殊字符开头或结尾'))
  }

  callback()
}
/**
 * 英文姓名校验规则
 */
export const validateChinese = (rule, value, callback) => {
  if (!value) {
    callback(new Error('请输入中文姓名'))
    return
  }

  // 验证是否只包含中文字符
  const chineseRegex = /^[\u4e00-\u9fa5]+$/
  if (!chineseRegex.test(value)) {
    callback(new Error('只能输入中文'))
    return
  }

  // 验证长度在2-6之间
  if (value.length < 2 || value.length > 6) {
    callback(new Error('长度应在2-6个字符之间'))
    return
  }

  callback()
}
/**
 * BMI校验规则
 */
export const validateBMI = (rule, value, callback) => {
  if (!value) {
    return
  }

  if (value < 19) {
    return callback(new Error('BMI值不能小于19'))
  }
  if (value >= 23.5) {
    return callback(new Error('BMI值不能大于23.5'))
  }
  callback()
}

/**
 * 手机号校验规则
 */
export const validatePhone = (rule, value, callback) => {
  if (!value) {
    return callback()
  }

  const phoneRegex = /^1[3-9]\d{9}$/
  if (!phoneRegex.test(value)) {
    return callback(new Error('请输入正确的手机号码'))
  }

  callback()
}
// 身份证验证相关方法

/**
 * 验证身份证号码是否合法
 * @param {string} idCard 身份证号码
 * @returns {boolean} 是否合法
 */
export function validIDCard(idCard) {
  if (!idCard) return false

  const idCardStr = idCard.toString().trim()

  // 长度验证
  if (idCardStr.length !== 15 && idCardStr.length !== 18) {
    return false
  }

  // 格式验证
  if (idCardStr.length === 15) {
    // 15位身份证：全部为数字
    if (!/^\d{15}$/.test(idCardStr)) {
      return false
    }

    // 验证出生日期
    const birthDateStr = '19' + idCardStr.substr(6, 6) // 19yyMMdd
    if (!validateBirthDate(birthDateStr)) {
      return false
    }

    // 验证省份代码
    const provinceCode = idCardStr.substr(0, 2)
    if (!validateProvinceCode(provinceCode)) {
      return false
    }
  } else if (idCardStr.length === 18) {
    // 18位身份证：前17位为数字，最后一位为数字或X（大小写）
    if (!/^\d{17}[\dXx]$/.test(idCardStr)) {
      return false
    }

    // 验证出生日期
    const birthDateStr = idCardStr.substr(6, 8) // yyyyMMdd
    if (!validateBirthDate(birthDateStr)) {
      return false
    }

    // 验证省份代码
    const provinceCode = idCardStr.substr(0, 2)
    if (!validateProvinceCode(provinceCode)) {
      return false
    }

    // 验证校验码
    if (!validateCheckCode(idCardStr.toUpperCase())) {
      return false
    }
  }

  return true
}

/**
 * 验证出生日期是否有效
 * @param {string} birthDateStr 出生日期字符串 (yyyyMMdd 或 yyMMdd)
 * @returns {boolean} 是否有效
 */
function validateBirthDate(birthDateStr) {
  // 统一为8位格式
  if (birthDateStr.length === 6) {
    birthDateStr = '19' + birthDateStr
  }

  if (birthDateStr.length !== 8) {
    return false
  }

  const year = parseInt(birthDateStr.substr(0, 4))
  const month = parseInt(birthDateStr.substr(4, 2))
  const day = parseInt(birthDateStr.substr(6, 2))

  // 验证年月日是否有效
  if (year < 1900 || year > new Date().getFullYear()) {
    return false
  }

  if (month < 1 || month > 12) {
    return false
  }

  // 验证每月天数
  const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

  // 闰年二月处理
  if (month === 2 && isLeapYear(year)) {
    if (day < 1 || day > 29) {
      return false
    }
  } else {
    if (day < 1 || day > daysInMonth[month - 1]) {
      return false
    }
  }

  // 验证日期不能晚于当前日期
  const birthDate = new Date(year, month - 1, day)
  const currentDate = new Date()
  if (birthDate > currentDate) {
    return false
  }

  // 验证年龄（最大150岁）
  const age = calculateAge(birthDate)
  if (age > 150) {
    return false
  }

  return true
}

/**
 * 验证省份代码
 * @param {string} code 省份代码
 * @returns {boolean} 是否有效
 */
function validateProvinceCode(code) {
  const provinceCodes = [
    '11',
    '12',
    '13',
    '14',
    '15', // 华北
    '21',
    '22',
    '23', // 东北
    '31',
    '32',
    '33',
    '34',
    '35',
    '36',
    '37', // 华东
    '41',
    '42',
    '43',
    '44',
    '45',
    '46', // 华中/华南
    '50',
    '51',
    '52',
    '53',
    '54', // 西南
    '61',
    '62',
    '63',
    '64',
    '65', // 西北
    '71',
    '81',
    '82',
    '91' // 港澳台及国外
  ]

  return provinceCodes.includes(code)
}

/**
 * 验证18位身份证的校验码
 * @param {string} idCard 18位身份证号码（需大写）
 * @returns {boolean} 是否校验通过
 */
function validateCheckCode(idCard) {
  // 校验码对应关系
  const checkCodeMap = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']

  // 系数表
  const coefficient = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]

  // 计算校验位
  let sum = 0
  for (let i = 0; i < 17; i++) {
    sum += parseInt(idCard.charAt(i)) * coefficient[i]
  }

  // 取模
  const mod = sum % 11

  // 获取计算出的校验码
  const expectedCheckCode = checkCodeMap[mod]

  // 与实际校验码比较
  const actualCheckCode = idCard.charAt(17)

  return expectedCheckCode === actualCheckCode
}

/**
 * 判断是否为闰年
 * @param {number} year 年份
 * @returns {boolean} 是否为闰年
 */
function isLeapYear(year) {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}

/**
 * 计算年龄
 * @param {Date} birthDate 出生日期
 * @returns {number} 年龄
 */
function calculateAge(birthDate) {
  const today = new Date()
  let age = today.getFullYear() - birthDate.getFullYear()
  const monthDiff = today.getMonth() - birthDate.getMonth()

  // 如果当前月份小于出生月份，或者月份相同但日期小于出生日期，则年龄减1
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
    age--
  }

  return age
}

/**
 * 从身份证提取信息
 * @param {string} idCard 身份证号码
 * @returns {Object|null} 身份证信息对象，无效返回null
 */
export function extractIDCardInfo(idCard) {
  if (!validIDCard(idCard)) {
    return null
  }

  const idCardStr = idCard.toString().trim().toUpperCase()

  // 提取出生日期
  let birthDateStr = ''
  if (idCardStr.length === 15) {
    birthDateStr = '19' + idCardStr.substr(6, 6)
  } else {
    birthDateStr = idCardStr.substr(6, 8)
  }

  const year = parseInt(birthDateStr.substr(0, 4))
  const month = parseInt(birthDateStr.substr(4, 2))
  const day = parseInt(birthDateStr.substr(6, 2))

  // 提取性别
  let genderCode = 0
  if (idCardStr.length === 15) {
    genderCode = parseInt(idCardStr.substr(14, 1))
  } else {
    genderCode = parseInt(idCardStr.substr(16, 1))
  }
  const gender = genderCode % 2 === 1 ? 1 : 0 // 1:男, 0:女

  // 提取省份代码
  const provinceCode = idCardStr.substr(0, 2)
  const province = getProvinceName(provinceCode)

  // 计算年龄
  const birthDate = new Date(year, month - 1, day)
  const age = calculateAge(birthDate)

  return {
    provinceCode,
    province,
    birthDate: `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`,
    year,
    month,
    day,
    gender,
    genderText: gender === 1 ? '男' : '女',
    age
  }
}

/**
 * 根据省份代码获取省份名称
 * @param {string} code 省份代码
 * @returns {string} 省份名称
 */
function getProvinceName(code) {
  const provinceMap = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外'
  }

  return provinceMap[code] || '未知'
}

/**
 * 身份证校验规则（用于Element Plus表单验证）
 */
export const validateIdCard = (rule, value, callback) => {
  if (!value) {
    // 如果值为空且字段不是必填的，直接通过校验
    // 如果必填，应该在rules中另外添加required规则
    return callback()
  }

  // 基本格式检查
  const idCardStr = value.toString().trim()

  if (idCardStr.length !== 15 && idCardStr.length !== 18) {
    return callback(new Error('身份证号码长度应为15位或18位'))
  }

  if (idCardStr.length === 15) {
    // 15位身份证：全部为数字
    if (!/^\d{15}$/.test(idCardStr)) {
      return callback(new Error('15位身份证号码应全部为数字'))
    }
  } else {
    // 18位身份证：前17位为数字，最后一位为数字或X
    if (!/^\d{17}[\dXx]$/.test(idCardStr)) {
      return callback(new Error('18位身份证号码格式不正确'))
    }
  }

  // 使用完整验证函数
  if (!validIDCard(value)) {
    return callback(new Error('请输入有效的身份证号码'))
  }

  callback()
}

/**
 * 简单验证身份证格式（不验证校验码和详细逻辑）
 */
export const validateIdCardSimple = (rule, value, callback) => {
  if (!value) {
    return callback()
  }

  const idCardStr = value.toString().trim()

  // 15位身份证验证
  if (idCardStr.length === 15) {
    if (!/^\d{15}$/.test(idCardStr)) {
      return callback(new Error('15位身份证号码应全部为数字'))
    }
  } else if (idCardStr.length === 18) {
    // 18位身份证验证
    if (!/^\d{17}[\dXx]$/.test(idCardStr)) {
      return callback(new Error('18位身份证号码格式不正确'))
    }
  } else {
    return callback(new Error('身份证号码长度应为15位或18位'))
  }

  callback()
}

// 将身份证验证方法添加到默认导出对象中
export default {
  validateEnglish,
  validateChinese,
  validatePhone,
  validateBMI,
  validateIdCard,
  validateIdCardSimple
}
