/**
 * 错误处理工具测试
 */

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { errorHandler, ErrorType, ErrorLevel, handleHttpError, handleBusinessError } from '../errorHandler'

// Mock Element Plus
vi.mock('element-plus', () => ({
  ElMessage: vi.fn(),
  ElNotification: vi.fn()
}))

describe('errorHandler', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    localStorage.clear()
    errorHandler.clearErrorLogs()
  })

  describe('错误标准化', () => {
    it('应该正确处理 Error 对象', () => {
      const error = new Error('Test error')
      
      errorHandler.handleError(error, 'Test context')
      
      const logs = errorHandler.getErrorLogs()
      expect(logs).toHaveLength(1)
      expect(logs[0].message).toBe('Test error')
      expect(logs[0].type).toBe(ErrorType.UNKNOWN)
      expect(logs[0].details.context).toBe('Test context')
    })

    it('应该正确识别网络错误', () => {
      const networkError = new Error('Network request failed')
      
      errorHandler.handleError(networkError)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs[0].type).toBe(ErrorType.NETWORK)
    })

    it('应该正确识别权限错误', () => {
      const permissionError = new Error('Permission denied')
      
      errorHandler.handleError(permissionError)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs[0].type).toBe(ErrorType.PERMISSION)
    })

    it('应该正确识别验证错误', () => {
      const validationError = new Error('Validation failed')
      
      errorHandler.handleError(validationError)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs[0].type).toBe(ErrorType.VALIDATION)
    })
  })

  describe('错误级别判断', () => {
    it('应该正确判断关键错误', () => {
      const criticalError = new Error('Critical system failure')
      
      errorHandler.handleError(criticalError)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs[0].level).toBe(ErrorLevel.CRITICAL)
    })

    it('应该正确判断高级别错误', () => {
      const highError = new Error('Network timeout')
      
      errorHandler.handleError(highError)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs[0].level).toBe(ErrorLevel.HIGH)
    })

    it('应该正确判断中级别错误', () => {
      const mediumError = new Error('Validation error')
      
      errorHandler.handleError(mediumError)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs[0].level).toBe(ErrorLevel.MEDIUM)
    })
  })

  describe('错误日志管理', () => {
    it('应该正确记录错误日志', () => {
      const error1 = new Error('Error 1')
      const error2 = new Error('Error 2')
      
      errorHandler.handleError(error1)
      errorHandler.handleError(error2)
      
      const logs = errorHandler.getErrorLogs()
      expect(logs).toHaveLength(2)
      expect(logs[0].message).toBe('Error 1')
      expect(logs[1].message).toBe('Error 2')
    })

    it('应该正确清空错误日志', () => {
      errorHandler.handleError(new Error('Test error'))
      expect(errorHandler.getErrorLogs()).toHaveLength(1)
      
      errorHandler.clearErrorLogs()
      expect(errorHandler.getErrorLogs()).toHaveLength(0)
    })

    it('应该限制错误日志队列大小', () => {
      // 添加超过最大队列大小的错误
      for (let i = 0; i < 105; i++) {
        errorHandler.handleError(new Error(`Error ${i}`))
      }
      
      const logs = errorHandler.getErrorLogs()
      expect(logs.length).toBeLessThanOrEqual(100)
    })
  })

  describe('自定义错误创建', () => {
    it('应该正确创建自定义错误', () => {
      const customError = errorHandler.createError(
        ErrorType.VALIDATION,
        ErrorLevel.MEDIUM,
        'Custom validation error',
        { field: 'email' }
      )
      
      expect(customError.type).toBe(ErrorType.VALIDATION)
      expect(customError.level).toBe(ErrorLevel.MEDIUM)
      expect(customError.message).toBe('Custom validation error')
      expect(customError.details.field).toBe('email')
      expect(customError.timestamp).toBeTypeOf('number')
    })
  })
})

describe('handleHttpError', () => {
  it('应该正确处理 400 错误', () => {
    const error = {
      response: {
        status: 400,
        statusText: 'Bad Request',
        data: { message: 'Invalid parameters' }
      },
      config: {
        url: '/api/test',
        method: 'POST'
      }
    }
    
    const errorInfo = handleHttpError(error)
    
    expect(errorInfo.type).toBe(ErrorType.VALIDATION)
    expect(errorInfo.message).toBe('Invalid parameters')
  })

  it('应该正确处理 401 错误', () => {
    const error = {
      response: {
        status: 401,
        statusText: 'Unauthorized',
        data: {}
      },
      config: {
        url: '/api/protected',
        method: 'GET'
      }
    }
    
    const errorInfo = handleHttpError(error)
    
    expect(errorInfo.type).toBe(ErrorType.PERMISSION)
    expect(errorInfo.level).toBe(ErrorLevel.HIGH)
    expect(errorInfo.message).toBe('登录已过期，请重新登录')
  })

  it('应该正确处理 500 错误', () => {
    const error = {
      response: {
        status: 500,
        statusText: 'Internal Server Error',
        data: {}
      },
      config: {
        url: '/api/test',
        method: 'GET'
      }
    }
    
    const errorInfo = handleHttpError(error)
    
    expect(errorInfo.type).toBe(ErrorType.API)
    expect(errorInfo.level).toBe(ErrorLevel.CRITICAL)
    expect(errorInfo.message).toBe('服务器内部错误')
  })

  it('应该正确处理网络错误', () => {
    const error = {
      request: {},
      config: {
        url: '/api/test',
        method: 'GET'
      }
    }
    
    const errorInfo = handleHttpError(error)
    
    expect(errorInfo.type).toBe(ErrorType.NETWORK)
    expect(errorInfo.level).toBe(ErrorLevel.HIGH)
    expect(errorInfo.message).toBe('网络连接失败，请检查网络设置')
  })
})

describe('handleBusinessError', () => {
  it('应该正确处理认证业务错误', () => {
    const errorInfo = handleBusinessError('AUTH_EXPIRED', '认证已过期')
    
    expect(errorInfo.type).toBe(ErrorType.PERMISSION)
    expect(errorInfo.level).toBe(ErrorLevel.HIGH)
    expect(errorInfo.message).toBe('认证已过期')
  })

  it('应该正确处理验证业务错误', () => {
    const errorInfo = handleBusinessError('VALID_EMAIL', '邮箱格式不正确')
    
    expect(errorInfo.type).toBe(ErrorType.VALIDATION)
    expect(errorInfo.level).toBe(ErrorLevel.LOW)
    expect(errorInfo.message).toBe('邮箱格式不正确')
  })

  it('应该正确处理网络业务错误', () => {
    const errorInfo = handleBusinessError('NETWORK_TIMEOUT', '请求超时')
    
    expect(errorInfo.type).toBe(ErrorType.NETWORK)
    expect(errorInfo.level).toBe(ErrorLevel.HIGH)
    expect(errorInfo.message).toBe('请求超时')
  })

  it('应该正确处理通用业务错误', () => {
    const errorInfo = handleBusinessError('UNKNOWN_ERROR', '未知错误')
    
    expect(errorInfo.type).toBe(ErrorType.API)
    expect(errorInfo.level).toBe(ErrorLevel.MEDIUM)
    expect(errorInfo.message).toBe('未知错误')
  })
})
