import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
  Logger,
} from '@nestjs/common';
import { Request, Response } from 'express';

/**
 * Global exception filter that catches all HTTP exceptions
 * and formats them consistently with proper logging
 */
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  private readonly logger = new Logger(HttpExceptionFilter.name);

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

    // Extract error details
    const errorDetails =
      typeof exceptionResponse === 'string'
        ? { message: exceptionResponse }
        : (exceptionResponse as any);

    // Build standardized error response
    const errorResponse = {
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      method: request.method,
      message: errorDetails.message || exception.message,
      error: errorDetails.error || HttpStatus[status],
      ...(errorDetails.details && { details: errorDetails.details }),
      ...(errorDetails.conflicts && { conflicts: errorDetails.conflicts }),
    };

    // Log error with appropriate level
    const logMessage = `[${request.method}] ${request.url} - ${status} - ${errorResponse.message}`;

    if (status >= 500) {
      this.logger.error(logMessage, exception.stack);
    } else if (status >= 400) {
      this.logger.warn(logMessage);
    } else {
      this.logger.log(logMessage);
    }

    // Log request details for debugging (exclude sensitive data)
    if (status >= 400) {
      const sanitizedBody = this.sanitizeRequestBody(request.body);
      this.logger.debug(
        `Request details: ${JSON.stringify({
          params: request.params,
          query: request.query,
          body: sanitizedBody,
          user: (request as any).user?.email,
        })}`,
      );
    }

    response.status(status).json(errorResponse);
  }

  /**
   * Remove sensitive fields from request body before logging
   */
  private sanitizeRequestBody(body: any): any {
    if (!body) return body;

    const sensitiveFields = ['password', 'token', 'apiKey', 'secret'];
    const sanitized = { ...body };

    sensitiveFields.forEach((field) => {
      if (sanitized[field]) {
        sanitized[field] = '***REDACTED***';
      }
    });

    return sanitized;
  }
}
