import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Request, Response } from 'express';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  private readonly logger = new Logger('HTTP');

  intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
    const request = context.switchToHttp().getRequest<Request>();
    const response = context.switchToHttp().getResponse<Response>();
    const { method, url, ip } = request;
    const correlationId = (request.headers['x-correlation-id'] as string) || 'no-correlation-id';
    const userAgent = request.get('user-agent') || '';
    const startTime = Date.now();

    return next.handle().pipe(
      tap({
        next: (): void => {
          const duration = Date.now() - startTime;
          this.logger.log(
            JSON.stringify({
              correlationId,
              method,
              url,
              statusCode: response.statusCode,
              duration: `${duration}ms`,
              ip,
              userAgent,
            }),
          );
        },
        error: (error): void => {
          const duration = Date.now() - startTime;
          this.logger.error(
            JSON.stringify({
              correlationId,
              method,
              url,
              statusCode: error.status || 500,
              duration: `${duration}ms`,
              ip,
              userAgent,
              error: error.message,
            }),
          );
        },
      }),
    );
  }
}
