import { Request, Response, NextFunction } from 'express'
import { ZodError } from 'zod'
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'
import { AppError } from '../lib/AppError'
import logger from '../lib/logger'

export function errorHandler(err: unknown, _req: Request, res: Response, _next: NextFunction) {
  if (err instanceof AppError) {
    return res.status(err.statusCode).json({
      success: false,
      error: { code: err.code, message: err.message },
    })
  }

  if (err instanceof ZodError) {
    return res.status(422).json({
      success: false,
      error: {
        code: 'VALIDATION_ERROR',
        message: '输入校验失败',
        details: err.errors.map((e) => ({ path: e.path.join('.'), message: e.message })),
      },
    })
  }

  if (err instanceof PrismaClientKnownRequestError) {
    if (err.code === 'P2002') {
      return res.status(400).json({
        success: false,
        error: { code: 'DUPLICATE', message: '数据已存在，请勿重复操作' },
      })
    }
    if (err.code === 'P2025') {
      return res.status(404).json({
        success: false,
        error: { code: 'NOT_FOUND', message: '记录不存在' },
      })
    }
  }

  if (typeof err === 'object' && err !== null && 'code' in err && 'message' in err) {
    const e = err as { code: string; message: string }
    const statusMap: Record<string, number> = {
      NOT_FOUND: 404,
      CONFLICT: 409,
      VALIDATION_ERROR: 422,
      PLAN_LIMIT: 403,
      AUTH_FAILED: 401,
      TOKEN_INVALID: 401,
      ACCOUNT_DISABLED: 403,
      DUPLICATE: 400,
    }
    return res.status(statusMap[e.code] || 400).json({
      success: false,
      error: { code: e.code, message: e.message },
    })
  }

  logger.error({ err }, 'Unhandled error')
  return res.status(500).json({
    success: false,
    error: { code: 'INTERNAL_ERROR', message: '服务器内部错误' },
  })
}
