/**
 * 全局错误处理工具
 */

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

// 错误类型枚举
export enum ErrorType {
  NETWORK = 'NETWORK',
  API = 'API',
  VALIDATION = 'VALIDATION',
  PERMISSION = 'PERMISSION',
  UNKNOWN = 'UNKNOWN'
}

// 错误级别枚举
export enum ErrorLevel {
  LOW = 'LOW',
  MEDIUM = 'MEDIUM',
  HIGH = 'HIGH',
  CRITICAL = 'CRITICAL'
}

// 错误信息接口
export interface ErrorInfo {
  type: ErrorType
  level: ErrorLevel
  message: string
  code?: string | number
  details?: any
  timestamp: number
  url?: string
  userAgent?: string
}

// 错误处理器类
class ErrorHandler {
  private errorQueue: ErrorInfo[] = []
  private maxQueueSize = 100

  /**
   * 处理错误
   */
  handleError(error: Error | ErrorInfo | any, context?: string): void {
    const errorInfo = this.normalizeError(error, context)
    
    // 记录错误
    this.logError(errorInfo)
    
    // 显示用户友好的错误信息
    this.showUserFriendlyMessage(errorInfo)
    
    // 上报错误（如果需要）
    this.reportError(errorInfo)
  }

  /**
   * 标准化错误信息
   */
  private normalizeError(error: any, context?: string): ErrorInfo {
    let errorInfo: ErrorInfo

    if (error instanceof Error) {
      errorInfo = {
        type: this.getErrorType(error),
        level: this.getErrorLevel(error),
        message: error.message,
        details: {
          name: error.name,
          stack: error.stack,
          context
        },
        timestamp: Date.now(),
        url: window.location.href,
        userAgent: navigator.userAgent
      }
    } else if (typeof error === 'object' && error.type) {
      // 已经是 ErrorInfo 格式
      errorInfo = error
    } else {
      // 其他类型的错误
      errorInfo = {
        type: ErrorType.UNKNOWN,
        level: ErrorLevel.MEDIUM,
        message: String(error),
        details: { context, originalError: error },
        timestamp: Date.now(),
        url: window.location.href,
        userAgent: navigator.userAgent
      }
    }

    return errorInfo
  }

  /**
   * 获取错误类型
   */
  private getErrorType(error: Error): ErrorType {
    const message = error.message.toLowerCase()
    
    if (message.includes('network') || message.includes('fetch')) {
      return ErrorType.NETWORK
    }
    
    if (message.includes('permission') || message.includes('unauthorized')) {
      return ErrorType.PERMISSION
    }
    
    if (message.includes('validation') || message.includes('invalid')) {
      return ErrorType.VALIDATION
    }
    
    if (error.name === 'TypeError' || error.name === 'ReferenceError') {
      return ErrorType.API
    }
    
    return ErrorType.UNKNOWN
  }

  /**
   * 获取错误级别
   */
  private getErrorLevel(error: Error): ErrorLevel {
    const message = error.message.toLowerCase()
    
    if (message.includes('critical') || message.includes('fatal')) {
      return ErrorLevel.CRITICAL
    }
    
    if (message.includes('network') || message.includes('timeout')) {
      return ErrorLevel.HIGH
    }
    
    if (message.includes('validation') || message.includes('permission')) {
      return ErrorLevel.MEDIUM
    }
    
    return ErrorLevel.LOW
  }

  /**
   * 记录错误
   */
  private logError(errorInfo: ErrorInfo): void {
    // 添加到错误队列
    this.errorQueue.push(errorInfo)
    
    // 保持队列大小
    if (this.errorQueue.length > this.maxQueueSize) {
      this.errorQueue.shift()
    }
    
    // 控制台输出
    const logMethod = this.getLogMethod(errorInfo.level)
    logMethod('Global Error:', errorInfo)
    
    // 存储到本地存储（可选）
    this.storeErrorLocally(errorInfo)
  }

  /**
   * 获取日志方法
   */
  private getLogMethod(level: ErrorLevel): typeof console.log {
    switch (level) {
      case ErrorLevel.CRITICAL:
      case ErrorLevel.HIGH:
        return console.error
      case ErrorLevel.MEDIUM:
        return console.warn
      default:
        return console.log
    }
  }

  /**
   * 显示用户友好的错误信息
   */
  private showUserFriendlyMessage(errorInfo: ErrorInfo): void {
    const userMessage = this.getUserFriendlyMessage(errorInfo)
    
    switch (errorInfo.level) {
      case ErrorLevel.CRITICAL:
        ElNotification({
          title: '系统错误',
          message: userMessage,
          type: 'error',
          duration: 0, // 不自动关闭
          showClose: true
        })
        break
        
      case ErrorLevel.HIGH:
        ElMessage({
          message: userMessage,
          type: 'error',
          duration: 5000,
          showClose: true
        })
        break
        
      case ErrorLevel.MEDIUM:
        ElMessage({
          message: userMessage,
          type: 'warning',
          duration: 3000
        })
        break
        
      default:
        // 低级别错误只在开发环境显示
        if (import.meta.env.DEV) {
          ElMessage({
            message: userMessage,
            type: 'info',
            duration: 2000
          })
        }
    }
  }

  /**
   * 获取用户友好的错误信息
   */
  private getUserFriendlyMessage(errorInfo: ErrorInfo): string {
    switch (errorInfo.type) {
      case ErrorType.NETWORK:
        return '网络连接异常，请检查网络设置后重试'
        
      case ErrorType.PERMISSION:
        return '您没有执行此操作的权限，请联系管理员'
        
      case ErrorType.VALIDATION:
        return errorInfo.message || '输入数据格式不正确，请检查后重试'
        
      case ErrorType.API:
        return '服务暂时不可用，请稍后重试'
        
      default:
        return errorInfo.message || '系统出现未知错误，请刷新页面重试'
    }
  }

  /**
   * 本地存储错误信息
   */
  private storeErrorLocally(errorInfo: ErrorInfo): void {
    try {
      const key = 'app_error_logs'
      const stored = localStorage.getItem(key)
      const logs = stored ? JSON.parse(stored) : []
      
      logs.push(errorInfo)
      
      // 只保留最近的100条错误
      if (logs.length > 100) {
        logs.splice(0, logs.length - 100)
      }
      
      localStorage.setItem(key, JSON.stringify(logs))
    } catch (error) {
      console.warn('Failed to store error locally:', error)
    }
  }

  /**
   * 上报错误到服务器
   */
  private reportError(errorInfo: ErrorInfo): void {
    // 只上报中高级别的错误
    if (errorInfo.level === ErrorLevel.LOW) {
      return
    }
    
    try {
      // 这里可以调用错误上报 API
      // fetch('/api/errors', {
      //   method: 'POST',
      //   headers: { 'Content-Type': 'application/json' },
      //   body: JSON.stringify(errorInfo)
      // }).catch(() => {}) // 静默处理上报失败
    } catch (error) {
      console.warn('Failed to report error:', error)
    }
  }

  /**
   * 获取错误日志
   */
  getErrorLogs(): ErrorInfo[] {
    return [...this.errorQueue]
  }

  /**
   * 清空错误日志
   */
  clearErrorLogs(): void {
    this.errorQueue = []
    localStorage.removeItem('app_error_logs')
  }

  /**
   * 创建自定义错误
   */
  createError(
    type: ErrorType,
    level: ErrorLevel,
    message: string,
    details?: any
  ): ErrorInfo {
    return {
      type,
      level,
      message,
      details,
      timestamp: Date.now(),
      url: window.location.href,
      userAgent: navigator.userAgent
    }
  }
}

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

// 全局错误处理函数
export const handleError = (error: any, context?: string) => {
  errorHandler.handleError(error, context)
}

// Promise 错误处理
export const handlePromiseError = (error: any, context?: string) => {
  console.warn('Unhandled Promise Rejection:', error)
  errorHandler.handleError(error, context || 'Promise Rejection')
}

// HTTP 错误处理
export const handleHttpError = (error: any): ErrorInfo => {
  let type = ErrorType.API
  let level = ErrorLevel.MEDIUM
  let message = '请求失败'
  
  if (error.response) {
    // 服务器响应错误
    const { status, data } = error.response
    
    switch (status) {
      case 400:
        type = ErrorType.VALIDATION
        // FastAPI返回的错误信息在detail字段
        message = data?.detail || data?.message || '请求参数错误'
        break
      case 401:
        type = ErrorType.PERMISSION
        level = ErrorLevel.HIGH
        message = '登录已过期，请重新登录'
        break
      case 403:
        type = ErrorType.PERMISSION
        level = ErrorLevel.HIGH
        message = '权限不足，无法访问'
        break
      case 404:
        type = ErrorType.API
        message = '请求的资源不存在'
        break
      case 429:
        type = ErrorType.API
        level = ErrorLevel.HIGH
        message = '请求过于频繁，请稍后重试'
        break
      case 500:
        type = ErrorType.API
        level = ErrorLevel.CRITICAL
        message = '服务器内部错误'
        break
      case 502:
      case 503:
      case 504:
        type = ErrorType.NETWORK
        level = ErrorLevel.HIGH
        message = '服务暂时不可用，请稍后重试'
        break
      default:
        message = data?.message || `请求失败 (${status})`
    }
    
    return errorHandler.createError(type, level, message, {
      status,
      statusText: error.response.statusText,
      url: error.config?.url,
      method: error.config?.method,
      data: error.config?.data,
      responseData: data
    })
  } else if (error.request) {
    // 网络错误
    return errorHandler.createError(
      ErrorType.NETWORK,
      ErrorLevel.HIGH,
      '网络连接失败，请检查网络设置',
      {
        timeout: error.code === 'ECONNABORTED',
        url: error.config?.url,
        method: error.config?.method
      }
    )
  } else {
    // 其他错误
    return errorHandler.createError(
      ErrorType.UNKNOWN,
      ErrorLevel.MEDIUM,
      error.message || '未知错误',
      { originalError: error }
    )
  }
}

// 业务错误处理
export const handleBusinessError = (code: string | number, message: string, details?: any): ErrorInfo => {
  let type = ErrorType.API
  let level = ErrorLevel.MEDIUM
  
  // 根据业务错误码判断类型和级别
  const codeStr = String(code)
  
  if (codeStr.startsWith('AUTH_')) {
    type = ErrorType.PERMISSION
    level = ErrorLevel.HIGH
  } else if (codeStr.startsWith('VALID_')) {
    type = ErrorType.VALIDATION
    level = ErrorLevel.LOW
  } else if (codeStr.startsWith('NETWORK_')) {
    type = ErrorType.NETWORK
    level = ErrorLevel.HIGH
  }
  
  return errorHandler.createError(type, level, message, { code, ...details })
}

// 表单验证错误处理
export const handleValidationError = (errors: Record<string, string[]>): void => {
  const firstError = Object.values(errors)[0]?.[0]
  if (firstError) {
    const errorInfo = errorHandler.createError(
      ErrorType.VALIDATION,
      ErrorLevel.LOW,
      firstError,
      { validationErrors: errors }
    )
    errorHandler.handleError(errorInfo)
  }
}

// 文件上传错误处理
export const handleUploadError = (error: any, fileName: string): void => {
  let message = '文件上传失败'
  
  if (error.code === 'FILE_TOO_LARGE') {
    message = `文件 "${fileName}" 过大，请选择较小的文件`
  } else if (error.code === 'FILE_TYPE_NOT_ALLOWED') {
    message = `文件 "${fileName}" 类型不支持`
  } else if (error.code === 'UPLOAD_TIMEOUT') {
    message = `文件 "${fileName}" 上传超时，请重试`
  }
  
  const errorInfo = errorHandler.createError(
    ErrorType.VALIDATION,
    ErrorLevel.MEDIUM,
    message,
    { fileName, originalError: error }
  )
  
  errorHandler.handleError(errorInfo)
}

// WebSocket 错误处理
export const handleWebSocketError = (error: Event, url: string): void => {
  const errorInfo = errorHandler.createError(
    ErrorType.NETWORK,
    ErrorLevel.HIGH,
    'WebSocket连接失败',
    { url, event: error }
  )
  
  errorHandler.handleError(errorInfo)
}

// 导出类型定义
