// 全局错误处理器
import type { App, ComponentPublicInstance } from 'vue'
import { ElMessage, ElNotification } from 'element-plus'
import { createLogger } from './logger'

const logger = createLogger('ErrorHandler')

// 错误类型
export interface AppError {
  code: number | string
  message: string
  details?: any
  stack?: string
  timestamp: Date
  source: 'vue' | 'api' | 'promise' | 'script' | 'unknown'
}

// 错误存储
const errorStore: AppError[] = []
const MAX_ERRORS = 50

// 添加错误到存储
const addError = (error: AppError) => {
  errorStore.unshift(error)
  if (errorStore.length > MAX_ERRORS) {
    errorStore.pop()
  }
}

// 获取错误历史
export const getErrors = () => [...errorStore]

// 清空错误
export const clearErrors = () => {
  errorStore.length = 0
}

// 格式化错误
const formatError = (
  err: any,
  source: AppError['source'] = 'unknown'
): AppError => {
  return {
    code: err.code || err.status || 'UNKNOWN',
    message: err.message || String(err),
    details: err.details || err.data || undefined,
    stack: err.stack,
    timestamp: new Date(),
    source,
  }
}

// 显示错误通知
const showErrorNotification = (error: AppError, showDetails = false) => {
  // 开发环境显示详细错误
  if (import.meta.env.DEV && showDetails) {
    ElNotification({
      title: `错误 [${error.code}]`,
      message: error.message,
      type: 'error',
      duration: 5000,
      dangerouslyUseHTMLString: true,
    })
  } else {
    // 生产环境显示友好提示
    ElMessage.error(error.message)
  }
}

// Vue 组件错误处理器
export const vueErrorHandler = (
  err: unknown,
  instance: ComponentPublicInstance | null,
  info: string
) => {
  const error = formatError(err, 'vue')
  error.details = {
    info,
    component: instance?.$options?.name || 'Unknown',
  }
  
  addError(error)
  logger.error(`Vue Error in ${info}`, error)
  
  // 显示错误提示
  showErrorNotification(error)
}

// Vue 警告处理器
export const vueWarnHandler = (msg: string, instance: ComponentPublicInstance | null, trace: string) => {
  if (!import.meta.env.DEV) return
  
  logger.warn('Vue Warning', {
    message: msg,
    component: instance?.$options?.name,
    trace,
  })
}

// Promise 错误处理器
export const promiseErrorHandler = (event: PromiseRejectionEvent) => {
  event.preventDefault()
  
  const error = formatError(event.reason, 'promise')
  addError(error)
  logger.error('Unhandled Promise Rejection', error)
  
  // 只在重要错误时显示通知
  if (error.code !== 401 && error.code !== 'NETWORK_ERROR') {
    showErrorNotification(error)
  }
}

// 脚本错误处理器
export const scriptErrorHandler = (event: ErrorEvent) => {
  const error = formatError(event.error || event.message, 'script')
  error.details = {
    filename: event.filename,
    lineno: event.lineno,
    colno: event.colno,
  }
  
  addError(error)
  logger.error('Script Error', error)
}

// API 错误处理器
export const handleApiError = (err: any): AppError => {
  const error = formatError(err, 'api')
  addError(error)
  logger.error('API Error', error)
  
  // 特定错误码处理
  switch (error.code) {
    case 401:
      // 认证失败，跳转登录
      localStorage.removeItem('auth_token')
      if (window.location.pathname !== '/login') {
        ElMessage.warning('登录已过期，请重新登录')
        setTimeout(() => {
          window.location.href = '/login'
        }, 1000)
      }
      break
    case 403:
      ElMessage.error('权限不足')
      break
    case 404:
      ElMessage.error('资源不存在')
      break
    case 500:
      ElMessage.error('服务器错误，请稍后重试')
      break
    default:
      showErrorNotification(error)
  }
  
  return error
}

// 安装全局错误处理器
export const setupErrorHandlers = (app: App) => {
  // Vue 错误处理
  app.config.errorHandler = vueErrorHandler
  
  // Vue 警告处理
  if (import.meta.env.DEV) {
    app.config.warnHandler = vueWarnHandler
  }
  
  // Promise 错误处理
  window.addEventListener('unhandledrejection', promiseErrorHandler)
  
  // 脚本错误处理
  window.addEventListener('error', scriptErrorHandler)
  
  logger.info('Global error handlers installed')
}

// 清理错误处理器
export const cleanupErrorHandlers = () => {
  window.removeEventListener('unhandledrejection', promiseErrorHandler)
  window.removeEventListener('error', scriptErrorHandler)
}

export default {
  setup: setupErrorHandlers,
  cleanup: cleanupErrorHandlers,
  getErrors,
  clearErrors,
  handleApiError,
}

