import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor, UseInterceptors } from '@nestjs/common'
import { Observable } from 'rxjs'
import { tap } from 'rxjs/operators'

export function RequestResponseLogging() {
	return UseInterceptors(LoggingInterceptor)
}

/**
 * Interceptor that logs the incoming request and the outgoing response
 * Can be used on Controllers or on specific APIs
 * It will log important parts of the request and response into DD
 */
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
	private readonly logger = new Logger(LoggingInterceptor.name)

	intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
		const request = context.switchToHttp().getRequest()
		const response = context.switchToHttp().getResponse()
		let requestData = {}

		requestData = {
			method: request.method,
			url: request.url,
			body: request.body,
			query_params: request.query,
			headers: request.headers,
		}

		return next.handle().pipe(
			tap((data) => {
				try {
					const responseData = {
						statusCode: response.statusCode,
						data,
						headers: response.headers,
					}

					// Log the outgoing response
					this.logger.log({
						message: `Logging outgoing response for '${request.url}'`,
						request: requestData,
						response: responseData,
					})
				} catch (error) {
					this.logger.error(error)
				}
			}),
		)
	}
}
