/**
 * 银行选择逻辑错误处理工具
 * 
 * @author ruoyi
 * @date 2025-12-24
 */

import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'

/**
 * 错误类型枚举
 */
export const ErrorTypes = {
  BANK_INFO_MISSING: 'BANK_INFO_MISSING',
  BANK_SERVICE_UNAVAILABLE: 'BANK_SERVICE_UNAVAILABLE',
  DATA_INCONSISTENCY: 'DATA_INCONSISTENCY',
  NETWORK_ERROR: 'NETWORK_ERROR',
  VALIDATION_ERROR: 'VALIDATION_ERROR',
  SUBMISSION_ERROR: 'SUBMISSION_ERROR'
}

/**
 * 网络重试配置
 */
const RETRY_CONFIG = {
  maxRetries: 3,
  retryIntervals: [1000, 2000, 5000], // 1秒, 2秒, 5秒
  retryableErrors: ['timeout', 'network', 'connection', 'ECONNREFUSED', 'ETIMEDOUT']
}

/**
 * 错误处理主类
 */
export class ErrorHandler {
  constructor() {
    this.retryAttempts = new Map() // 存储重试次数
  }

  /**
   * 处理API响应错误
   * @param {Object} error - 错误对象
   * @param {Object} context - 错误上下文
   * @returns {Promise} 处理结果
   */
  async handleApiError(error, context = {}) {
    console.error('API错误:', error)

    // 解析错误信息
    const errorInfo = this.parseError(error)
    
    // 根据错误类型进行处理
    switch (errorInfo.type) {
      case ErrorTypes.BANK_INFO_MISSING:
        return this.handleBankInfoMissing(errorInfo, context)
      
      case ErrorTypes.BANK_SERVICE_UNAVAILABLE:
        return this.handleBankServiceUnavailable(errorInfo, context)
      
      case ErrorTypes.DATA_INCONSISTENCY:
        return this.handleDataInconsistency(errorInfo, context)
      
      case ErrorTypes.NETWORK_ERROR:
        return this.handleNetworkError(errorInfo, context)
      
      case ErrorTypes.VALIDATION_ERROR:
        return this.handleValidationError(errorInfo, context)
      
      case ErrorTypes.SUBMISSION_ERROR:
        return this.handleSubmissionError(errorInfo, context)
      
      default:
        return this.handleGenericError(errorInfo, context)
    }
  }

  /**
   * 解析错误信息
   * @param {Object} error - 原始错误对象
   * @returns {Object} 解析后的错误信息
   */
  parseError(error) {
    let errorInfo = {
      type: 'UNKNOWN_ERROR',
      message: '未知错误',
      retryable: false,
      suggestions: [],
      data: null
    }

    if (error.response) {
      // HTTP响应错误
      const responseData = error.response.data
      
      if (responseData && responseData.errorType) {
        errorInfo.type = responseData.errorType
        errorInfo.message = responseData.msg || responseData.message || '操作失败'
        errorInfo.retryable = responseData.retryable || false
        errorInfo.suggestions = responseData.suggestions || []
        errorInfo.data = responseData
      } else {
        // 根据HTTP状态码判断错误类型
        const status = error.response.status
        if (status >= 500) {
          errorInfo.type = ErrorTypes.NETWORK_ERROR
          errorInfo.message = '服务器内部错误，请稍后重试'
          errorInfo.retryable = true
        } else if (status === 404) {
          errorInfo.message = '请求的资源不存在'
        } else if (status === 403) {
          errorInfo.message = '没有权限执行此操作'
        } else if (status === 401) {
          errorInfo.message = '登录已过期，请重新登录'
        } else {
          errorInfo.message = responseData?.msg || responseData?.message || '请求失败'
        }
      }
    } else if (error.request) {
      // 网络请求错误
      errorInfo.type = ErrorTypes.NETWORK_ERROR
      errorInfo.message = '网络连接失败，请检查网络设置'
      errorInfo.retryable = true
    } else {
      // 其他错误
      errorInfo.message = error.message || '操作失败'
      
      // 检查是否为网络相关错误
      if (this.isNetworkError(error.message)) {
        errorInfo.type = ErrorTypes.NETWORK_ERROR
        errorInfo.retryable = true
      }
    }

    return errorInfo
  }

  /**
   * 处理银行信息缺失错误
   */
  async handleBankInfoMissing(errorInfo, context) {
    const missingFields = errorInfo.data?.missingFields || []
    const suggestions = errorInfo.data?.suggestions || []

    let message = '银行信息不完整'
    if (missingFields.length > 0) {
      message += '，缺少：' + missingFields.join('、')
    }

    const result = await ElMessageBox.confirm(
      message + '\n\n建议：\n' + suggestions.join('\n'),
      '银行信息不完整',
      {
        confirmButtonText: '去完善',
        cancelButtonText: '取消',
        type: 'warning',
        showClose: false
      }
    ).catch(() => ({ action: 'cancel' }))

    return {
      action: result === 'confirm' ? 'fix_bank_info' : 'cancel',
      data: errorInfo.data
    }
  }

  /**
   * 处理银行服务不可用错误
   */
  async handleBankServiceUnavailable(errorInfo, context) {
    const alternatives = errorInfo.data?.alternatives || []
    const hasAlternatives = errorInfo.data?.hasAlternatives || false

    let message = '所选银行服务暂时不可用'
    let options = {
      confirmButtonText: '重试',
      cancelButtonText: '取消',
      type: 'warning'
    }

    if (hasAlternatives && alternatives.length > 0) {
      message += `\n\n系统为您找到了 ${alternatives.length} 个备选银行：`
      alternatives.slice(0, 3).forEach((bank, index) => {
        message += `\n${index + 1}. ${bank.bankName} (利率: ${(bank.interestRate * 100).toFixed(2)}%)`
      })
      
      options.confirmButtonText = '选择备选银行'
      options.cancelButtonText = '稍后重试'
    }

    const result = await ElMessageBox.confirm(message, '银行服务不可用', options)
      .catch(() => ({ action: 'cancel' }))

    if (result === 'confirm' && hasAlternatives) {
      return {
        action: 'select_alternative',
        data: { alternatives }
      }
    } else if (result === 'confirm') {
      return {
        action: 'retry',
        data: errorInfo.data
      }
    } else {
      return {
        action: 'cancel',
        data: errorInfo.data
      }
    }
  }

  /**
   * 处理数据不一致错误
   */
  async handleDataInconsistency(errorInfo, context) {
    const result = await ElMessageBox.confirm(
      '系统检测到数据不一致，是否尝试自动修复？\n\n自动修复将：\n• 同步银行选择状态\n• 重新计算月还款额\n• 修正提交状态',
      '数据不一致',
      {
        confirmButtonText: '自动修复',
        cancelButtonText: '手动处理',
        type: 'warning'
      }
    ).catch(() => ({ action: 'cancel' }))

    return {
      action: result === 'confirm' ? 'auto_repair' : 'manual_fix',
      data: errorInfo.data
    }
  }

  /**
   * 处理网络错误
   */
  async handleNetworkError(errorInfo, context) {
    const operation = context.operation || '操作'
    const retryKey = `${operation}_${Date.now()}`
    
    // 获取当前重试次数
    let retryCount = this.retryAttempts.get(operation) || 0
    
    if (retryCount >= RETRY_CONFIG.maxRetries) {
      // 超过最大重试次数
      this.retryAttempts.delete(operation)
      
      ElMessage.error({
        message: `${operation}失败，已重试${retryCount}次。请检查网络连接或稍后再试。`,
        duration: 5000
      })
      
      return { action: 'give_up', retryCount }
    }

    // 计算等待时间
    const waitTime = retryCount < RETRY_CONFIG.retryIntervals.length 
      ? RETRY_CONFIG.retryIntervals[retryCount] 
      : RETRY_CONFIG.retryIntervals[RETRY_CONFIG.retryIntervals.length - 1]

    // 显示重试提示
    const result = await ElMessageBox.confirm(
      `网络连接失败，将在 ${waitTime / 1000} 秒后自动重试（第 ${retryCount + 1} 次）\n\n您也可以：`,
      '网络错误',
      {
        confirmButtonText: '立即重试',
        cancelButtonText: '取消操作',
        type: 'warning'
      }
    ).catch(() => ({ action: 'cancel' }))

    if (result === 'confirm') {
      // 增加重试次数
      this.retryAttempts.set(operation, retryCount + 1)
      
      return {
        action: 'retry_now',
        retryCount: retryCount + 1,
        waitTime: 0
      }
    } else {
      // 用户取消
      this.retryAttempts.delete(operation)
      return { action: 'cancel', retryCount }
    }
  }

  /**
   * 处理验证错误
   */
  async handleValidationError(errorInfo, context) {
    const errors = errorInfo.data?.errors || []
    const warnings = errorInfo.data?.warnings || []

    let message = '信息验证失败'
    if (errors.length > 0) {
      message += '\n\n错误：\n' + errors.map((err, index) => `${index + 1}. ${err}`).join('\n')
    }
    if (warnings.length > 0) {
      message += '\n\n警告：\n' + warnings.map((warn, index) => `${index + 1}. ${warn}`).join('\n')
    }

    ElMessage.error({
      message: errorInfo.message,
      duration: 5000
    })

    // 显示详细信息
    if (errors.length > 0 || warnings.length > 0) {
      ElNotification.warning({
        title: '验证详情',
        message: message,
        duration: 8000,
        position: 'bottom-right'
      })
    }

    return {
      action: 'fix_validation',
      data: { errors, warnings }
    }
  }

  /**
   * 处理提交错误
   */
  async handleSubmissionError(errorInfo, context) {
    const result = await ElMessageBox.confirm(
      errorInfo.message + '\n\n是否重新尝试提交？',
      '提交失败',
      {
        confirmButtonText: '重新提交',
        cancelButtonText: '稍后再试',
        type: 'error'
      }
    ).catch(() => ({ action: 'cancel' }))

    return {
      action: result === 'confirm' ? 'retry_submit' : 'cancel',
      data: errorInfo.data
    }
  }

  /**
   * 处理通用错误
   */
  async handleGenericError(errorInfo, context) {
    ElMessage.error({
      message: errorInfo.message,
      duration: 5000
    })

    if (errorInfo.retryable) {
      const result = await ElMessageBox.confirm(
        errorInfo.message + '\n\n是否重试？',
        '操作失败',
        {
          confirmButtonText: '重试',
          cancelButtonText: '取消',
          type: 'error'
        }
      ).catch(() => ({ action: 'cancel' }))

      return {
        action: result === 'confirm' ? 'retry' : 'cancel',
        data: errorInfo.data
      }
    }

    return { action: 'acknowledge', data: errorInfo.data }
  }

  /**
   * 自动重试网络请求
   * @param {Function} requestFn - 请求函数
   * @param {Object} context - 上下文信息
   * @returns {Promise} 请求结果
   */
  async autoRetryRequest(requestFn, context = {}) {
    const operation = context.operation || 'request'
    let lastError = null

    for (let attempt = 0; attempt <= RETRY_CONFIG.maxRetries; attempt++) {
      try {
        const result = await requestFn()
        
        // 成功后清除重试记录
        this.retryAttempts.delete(operation)
        
        if (attempt > 0) {
          ElMessage.success(`${operation}成功（重试${attempt}次后）`)
        }
        
        return result
      } catch (error) {
        lastError = error
        
        // 检查是否为可重试的网络错误
        if (!this.isRetryableError(error) || attempt === RETRY_CONFIG.maxRetries) {
          throw error
        }

        // 等待重试间隔
        const waitTime = attempt < RETRY_CONFIG.retryIntervals.length 
          ? RETRY_CONFIG.retryIntervals[attempt] 
          : RETRY_CONFIG.retryIntervals[RETRY_CONFIG.retryIntervals.length - 1]

        console.log(`${operation}失败，${waitTime}ms后进行第${attempt + 1}次重试`)
        
        // 显示重试提示
        ElMessage.warning({
          message: `${operation}失败，正在重试...（${attempt + 1}/${RETRY_CONFIG.maxRetries}）`,
          duration: 2000
        })

        await this.sleep(waitTime)
      }
    }

    throw lastError
  }

  /**
   * 检查是否为网络错误
   */
  isNetworkError(message) {
    if (!message) return false
    
    const networkKeywords = ['timeout', 'network', 'connection', 'ECONNREFUSED', 'ETIMEDOUT', 'fetch']
    return networkKeywords.some(keyword => message.toLowerCase().includes(keyword.toLowerCase()))
  }

  /**
   * 检查是否为可重试的错误
   */
  isRetryableError(error) {
    if (error.response) {
      // HTTP错误，5xx可重试
      return error.response.status >= 500
    }
    
    if (error.request) {
      // 网络请求错误，可重试
      return true
    }
    
    // 检查错误消息
    const message = error.message || ''
    return RETRY_CONFIG.retryableErrors.some(keyword => 
      message.toLowerCase().includes(keyword.toLowerCase())
    )
  }

  /**
   * 清除重试记录
   */
  clearRetryAttempts(operation = null) {
    if (operation) {
      this.retryAttempts.delete(operation)
    } else {
      this.retryAttempts.clear()
    }
  }

  /**
   * 睡眠函数
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
  }
}

// 创建全局错误处理器实例
export const errorHandler = new ErrorHandler()

/**
 * 便捷的错误处理函数
 */
export const handleError = (error, context = {}) => {
  return errorHandler.handleApiError(error, context)
}

/**
 * 自动重试请求的便捷函数
 */
export const retryRequest = (requestFn, context = {}) => {
  return errorHandler.autoRetryRequest(requestFn, context)
}

/**
 * 显示友好的错误提示
 */
export const showFriendlyError = (errorType, message, suggestions = []) => {
  let title = '操作失败'
  let type = 'error'

  switch (errorType) {
    case ErrorTypes.BANK_INFO_MISSING:
      title = '银行信息不完整'
      type = 'warning'
      break
    case ErrorTypes.BANK_SERVICE_UNAVAILABLE:
      title = '银行服务不可用'
      type = 'warning'
      break
    case ErrorTypes.DATA_INCONSISTENCY:
      title = '数据不一致'
      type = 'warning'
      break
    case ErrorTypes.NETWORK_ERROR:
      title = '网络连接问题'
      type = 'error'
      break
    case ErrorTypes.VALIDATION_ERROR:
      title = '信息验证失败'
      type = 'warning'
      break
  }

  let fullMessage = message
  if (suggestions.length > 0) {
    fullMessage += '\n\n建议：\n' + suggestions.join('\n')
  }

  ElNotification({
    title,
    message: fullMessage,
    type,
    duration: 8000,
    position: 'bottom-right'
  })
}

export default {
  ErrorHandler,
  errorHandler,
  handleError,
  retryRequest,
  showFriendlyError,
  ErrorTypes
}