/**
 * 管理员数据库操作异常过滤器
 *
 * 功能描述：
 * - 统一处理管理员数据库管理操作中的异常
 * - 标准化错误响应格式
 * - 记录详细的错误日志
 * - 提供用户友好的错误信息
 *
 * 职责分离：
 * - 异常捕获：捕获所有未处理的异常
 * - 错误转换：将系统异常转换为用户友好的错误信息
 * - 日志记录：记录详细的错误信息用于调试
 * - 响应格式化：统一错误响应的格式
 *
 * 支持的异常类型：
 * - BadRequestException: 400 - 请求参数错误
 * - UnauthorizedException: 401 - 未授权访问
 * - ForbiddenException: 403 - 权限不足
 * - NotFoundException: 404 - 资源不存在
 * - ConflictException: 409 - 资源冲突
 * - UnprocessableEntityException: 422 - 数据验证失败
 * - InternalServerErrorException: 500 - 系统内部错误
 *
 * 最近修改：
 * - 2026-01-08: 注释规范优化 - 修正@author字段，更新版本号和修改记录 (修改者: moyin)
 * - 2026-01-08: 功能新增 - 创建管理员数据库异常过滤器 (修改者: assistant)
 *
 * @author moyin
 * @version 1.0.1
 * @since 2026-01-08
 * @lastModified 2026-01-08
 */

import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
  Logger,
  BadRequestException,
  UnauthorizedException,
  ForbiddenException,
  NotFoundException,
  ConflictException,
  UnprocessableEntityException,
  InternalServerErrorException
} from '@nestjs/common';
import { Request, Response } from 'express';
import { SENSITIVE_FIELDS } from './admin_constants';
import { generateRequestId, getCurrentTimestamp } from './admin_utils';

/**
 * 错误响应接口
 */
interface ErrorResponse {
  success: false;
  message: string;
  error_code: string;
  details?: {
    field?: string;
    constraint?: string;
    received_value?: any;
  }[];
  timestamp: string;
  request_id: string;
  path: string;
  method: string;
}

@Catch()
export class AdminDatabaseExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(AdminDatabaseExceptionFilter.name);

  catch(exception: any, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const errorResponse = this.buildErrorResponse(exception, request);

    // 记录错误日志
    this.logError(exception, request, errorResponse);

    response.status(errorResponse.status).json({
      success: errorResponse.body.success,
      message: errorResponse.body.message,
      error_code: errorResponse.body.error_code,
      details: errorResponse.body.details,
      timestamp: errorResponse.body.timestamp,
      request_id: errorResponse.body.request_id,
      path: errorResponse.body.path,
      method: errorResponse.body.method
    });
  }

  /**
   * 构建错误响应
   *
   * @param exception 异常对象
   * @param request 请求对象
   * @returns 错误响应对象
   */
  private buildErrorResponse(exception: any, request: Request): { status: number; body: ErrorResponse } {
    let status: number;
    let message: string;
    let error_code: string;
    let details: any[] | undefined;

    if (exception instanceof HttpException) {
      status = exception.getStatus();
      const exceptionResponse = exception.getResponse();

      if (typeof exceptionResponse === 'string') {
        message = exceptionResponse;
      } else if (typeof exceptionResponse === 'object' && exceptionResponse !== null) {
        const responseObj = exceptionResponse as any;
        message = responseObj.message || responseObj.error || exception.message;
        details = responseObj.details;
      } else {
        message = exception.message;
      }

      // 根据异常类型设置错误码
      error_code = this.getErrorCodeByException(exception);
    } else {
      // 未知异常，返回500
      status = HttpStatus.INTERNAL_SERVER_ERROR;
      message = '系统内部错误，请稍后重试';
      error_code = 'INTERNAL_SERVER_ERROR';
    }

    const body: ErrorResponse = {
      success: false,
      message,
      error_code,
      details,
      timestamp: getCurrentTimestamp(),
      request_id: generateRequestId('err'),
      path: request.url,
      method: request.method
    };

    return { status, body };
  }

  /**
   * 根据异常类型获取错误码
   *
   * @param exception 异常对象
   * @returns 错误码
   */
  private getErrorCodeByException(exception: HttpException): string {
    if (exception instanceof BadRequestException) {
      return 'BAD_REQUEST';
    }
    if (exception instanceof UnauthorizedException) {
      return 'UNAUTHORIZED';
    }
    if (exception instanceof ForbiddenException) {
      return 'FORBIDDEN';
    }
    if (exception instanceof NotFoundException) {
      return 'NOT_FOUND';
    }
    if (exception instanceof ConflictException) {
      return 'CONFLICT';
    }
    if (exception instanceof UnprocessableEntityException) {
      return 'UNPROCESSABLE_ENTITY';
    }
    if (exception instanceof InternalServerErrorException) {
      return 'INTERNAL_SERVER_ERROR';
    }

    // 根据HTTP状态码设置错误码
    const status = exception.getStatus();
    switch (status) {
      case HttpStatus.BAD_REQUEST:
        return 'BAD_REQUEST';
      case HttpStatus.UNAUTHORIZED:
        return 'UNAUTHORIZED';
      case HttpStatus.FORBIDDEN:
        return 'FORBIDDEN';
      case HttpStatus.NOT_FOUND:
        return 'NOT_FOUND';
      case HttpStatus.CONFLICT:
        return 'CONFLICT';
      case HttpStatus.UNPROCESSABLE_ENTITY:
        return 'UNPROCESSABLE_ENTITY';
      case HttpStatus.TOO_MANY_REQUESTS:
        return 'TOO_MANY_REQUESTS';
      case HttpStatus.INTERNAL_SERVER_ERROR:
        return 'INTERNAL_SERVER_ERROR';
      case HttpStatus.BAD_GATEWAY:
        return 'BAD_GATEWAY';
      case HttpStatus.SERVICE_UNAVAILABLE:
        return 'SERVICE_UNAVAILABLE';
      case HttpStatus.GATEWAY_TIMEOUT:
        return 'GATEWAY_TIMEOUT';
      default:
        return 'UNKNOWN_ERROR';
    }
  }

  /**
   * 记录错误日志
   *
   * @param exception 异常对象
   * @param request 请求对象
   * @param errorResponse 错误响应对象
   */
  private logError(exception: any, request: Request, errorResponse: { status: number; body: ErrorResponse }): void {
    const { status, body } = errorResponse;

    const logContext = {
      request_id: body.request_id,
      method: request.method,
      url: request.url,
      user_agent: request.get('User-Agent'),
      ip: request.ip,
      status,
      error_code: body.error_code,
      message: body.message,
      timestamp: body.timestamp
    };

    if (status >= 500) {
      // 服务器错误，记录详细的错误信息
      this.logger.error('服务器内部错误', {
        ...logContext,
        stack: exception instanceof Error ? exception.stack : undefined,
        exception_type: exception.constructor?.name,
        details: body.details
      });
    } else if (status >= 400) {
      // 客户端错误，记录警告信息
      this.logger.warn('客户端请求错误', {
        ...logContext,
        request_body: this.sanitizeRequestBody(request.body),
        query_params: request.query
      });
    } else {
      // 其他情况，记录普通日志
      this.logger.log('请求处理异常', logContext);
    }
  }

  /**
   * 清理请求体中的敏感信息
   *
   * @param body 请求体
   * @returns 清理后的请求体
   */
  private sanitizeRequestBody(body: any): any {
    if (!body || typeof body !== 'object') {
      return body;
    }

    const sanitized = { ...body };

    for (const field of SENSITIVE_FIELDS) {
      if (sanitized[field]) {
        sanitized[field] = '[REDACTED]';
      }
    }

    return sanitized;
  }
}