/**
 * 统一错误处理工具
 * 提供统一的错误提示和处理机制
 */

/**
 * 错误类型映射
 */
const ERROR_TYPES = {
  NETWORK: 'network',
  AUTH: 'auth',
  BUSINESS: 'business',
  UNKNOWN: 'unknown'
}

/**
 * 错误消息映射
 */
const ERROR_MESSAGES = {
  // 网络错误
  'request:fail': '网络连接失败，请检查网络设置',
  'request:fail timeout': '请求超时，请稍后重试',
  'request:fail abort': '请求已取消',
  
  // 认证错误
  401: '登录已过期，请重新登录',
  403: '没有权限访问',
  
  // 业务错误
  400: '请求参数错误',
  404: '请求的资源不存在',
  500: '服务器错误，请稍后重试',
  
  // 默认错误
  default: '操作失败，请稍后重试'
}

/**
 * 判断错误类型
 * @param {object} error - 错误对象
 * @returns {string} 错误类型
 */
function getErrorType(error) {
  if (!error) return ERROR_TYPES.UNKNOWN
  
  // 网络错误
  if (error.errMsg && error.errMsg.includes('request:fail')) {
    return ERROR_TYPES.NETWORK
  }
  
  // 认证错误
  if (error.code === 401 || error.statusCode === 401) {
    return ERROR_TYPES.AUTH
  }
  
  // 业务错误
  if (error.code || error.statusCode) {
    return ERROR_TYPES.BUSINESS
  }
  
  return ERROR_TYPES.UNKNOWN
}

/**
 * 获取错误消息
 * @param {object} error - 错误对象
 * @returns {string} 错误消息
 */
function getErrorMessage(error) {
  if (!error) return ERROR_MESSAGES.default
  
  // 优先使用后端返回的错误消息
  if (error.message) return error.message
  if (error.error) return error.error
  if (error.msg) return error.msg
  
  // 根据错误码获取消息
  const code = error.code || error.statusCode
  if (code && ERROR_MESSAGES[code]) {
    return ERROR_MESSAGES[code]
  }
  
  // 根据错误信息获取消息
  if (error.errMsg && ERROR_MESSAGES[error.errMsg]) {
    return ERROR_MESSAGES[error.errMsg]
  }
  
  return ERROR_MESSAGES.default
}

/**
 * 显示错误提示
 * @param {object} error - 错误对象
 * @param {object} options - 选项
 */
function showError(error, options = {}) {
  const {
    silent = false,        // 是否静默（不显示提示）
    duration = 2000,       // 提示持续时间
    icon = 'none',         // 图标类型
    mask = false           // 是否显示透明蒙层
  } = options
  
  if (silent) return
  
  const message = getErrorMessage(error)
  const type = getErrorType(error)
  
  // 认证错误不显示toast，由auth模块处理
  if (type === ERROR_TYPES.AUTH) {
    return
  }
  
  wx.showToast({
    title: message,
    icon,
    duration,
    mask
  })
}

/**
 * 处理API错误
 * @param {object} error - 错误对象
 * @param {object} options - 选项
 * @returns {object} 处理后的错误对象
 */
function handleApiError(error, options = {}) {
  const {
    showToast = true,      // 是否显示错误提示
    logError = true,       // 是否记录错误日志
    customMessage = null   // 自定义错误消息
  } = options
  
  // 记录错误日志
  if (logError) {
    console.error('[Error Handler]', error)
  }
  
  // 显示错误提示
  if (showToast) {
    showError(error, {
      silent: false,
      duration: 2000
    })
  }
  
  // 返回标准化的错误对象
  return {
    type: getErrorType(error),
    message: customMessage || getErrorMessage(error),
    code: error.code || error.statusCode || -1,
    originalError: error
  }
}

/**
 * 错误重试机制
 * @param {function} fn - 要重试的函数
 * @param {object} options - 选项
 * @returns {Promise}
 */
async function retryOnError(fn, options = {}) {
  const {
    maxRetries = 3,        // 最大重试次数
    retryDelay = 1000,     // 重试延迟（毫秒）
    onRetry = null         // 重试回调
  } = options
  
  let lastError = null
  
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn()
    } catch (error) {
      lastError = error
      
      // 认证错误不重试
      if (getErrorType(error) === ERROR_TYPES.AUTH) {
        throw error
      }
      
      // 最后一次重试失败，抛出错误
      if (i === maxRetries - 1) {
        throw error
      }
      
      // 执行重试回调
      if (onRetry) {
        onRetry(i + 1, maxRetries)
      }
      
      // 等待后重试
      await new Promise(resolve => setTimeout(resolve, retryDelay))
    }
  }
  
  throw lastError
}

/**
 * 检查网络状态
 * @returns {Promise<boolean>}
 */
function checkNetworkStatus() {
  return new Promise((resolve) => {
    wx.getNetworkType({
      success: (res) => {
        const networkType = res.networkType
        if (networkType === 'none') {
          wx.showToast({
            title: '网络未连接',
            icon: 'none',
            duration: 2000
          })
          resolve(false)
        } else {
          resolve(true)
        }
      },
      fail: () => {
        resolve(true) // 获取失败时假设网络正常
      }
    })
  })
}

module.exports = {
  ERROR_TYPES,
  ERROR_MESSAGES,
  getErrorType,
  getErrorMessage,
  showError,
  handleApiError,
  retryOnError,
  checkNetworkStatus
}
