// 自定义应用错误类
class AppError extends Error {
  constructor(message, statusCode) {
    super(message)
    this.statusCode = statusCode
    this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error'
    this.isOperational = true

    Error.captureStackTrace(this, this.constructor)
  }
}

// 异步错误处理包装器
const catchAsync = (fn) => {
  return (req, res, next) => {
    fn(req, res, next).catch(next)
  }
}

// 404错误处理
const notFound = (req, res, next) => {
  const error = new AppError(`无法找到 ${req.originalUrl}`, 404)
  next(error)
}

// MySQL重复键错误处理
const handleDuplicateFieldsDB = (err) => {
  // 提取重复的字段值
  let value = '未知字段'
  if (err.sqlMessage && err.sqlMessage.includes('Duplicate entry')) {
    const match = err.sqlMessage.match(/Duplicate entry '([^']+)' for key '([^']+)'/)
    if (match && match[1]) {
      value = match[1]
    }
  }
  const message = `字段值 ${value} 已存在，请使用其他值`
  return new AppError(message, 400)
}

// MySQL验证错误处理
const handleValidationErrorDB = (err) => {
  // MySQL验证错误通常在sqlMessage中包含详细信息
  const message = err.sqlMessage || '输入数据无效'
  return new AppError(message, 400)
}

// JWT错误处理
const handleJWTError = () =>
  new AppError('无效的token，请重新登录', 401)

const handleJWTExpiredError = () =>
  new AppError('token已过期，请重新登录', 401)

// MySQL连接错误处理
const handleDBConnectionError = (err) => {
  return new AppError('数据库连接失败，请稍后再试', 503)
}

// 全局错误处理中间件
const globalErrorHandler = (err, req, res, next) => {
  err.statusCode = err.statusCode || 500
  err.status = err.status || 'error'
  err.message = err.message || '服务器内部错误'

  // 开发环境详细错误信息
  if (process.env.NODE_ENV === 'development') {
    res.status(err.statusCode).json({
      status: err.status,
      error: err,
      message: err.message,
      stack: err.stack
    })
  } else {
    // 生产环境：区分不同类型的错误并提供适当的响应
    let error = { ...err, message: err.message } // 创建错误副本
    
    // 数据库错误处理
    if (error.code === 'ER_DUP_ENTRY') error = handleDuplicateFieldsDB(error)
    if (error.code === 'ER_NO_REFERENCED_ROW_2' || error.code === 'ER_BAD_NULL_ERROR') {
      error = handleValidationErrorDB(error)
    }
    if (error.code === 'ECONNREFUSED') error = handleDBConnectionError(error)
    
    // JWT错误处理
    if (error.name === 'JsonWebTokenError') error = handleJWTError()
    if (error.name === 'TokenExpiredError') error = handleJWTExpiredError()

    // 生产环境简化错误信息
    res.status(error.statusCode || 500).json({
      status: error.status || 'error',
      message: error.message || '服务器内部错误'
    })
  }
}

module.exports = {
  AppError,
  catchAsync,
  notFound,
  globalErrorHandler,
  handleDuplicateFieldsDB,
  handleValidationErrorDB,
  handleJWTError,
  handleJWTExpiredError,
  handleDBConnectionError
}