import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
import { ApiLog } from './entities/api-log.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as moment from 'moment';

@Injectable()
export class ApiLogInterceptor implements NestMiddleware {
  constructor(
    @InjectRepository(ApiLog)
    private readonly logRepository: Repository<ApiLog>,
  ) {}

  use(req: Request, res: Response, next: () => void) {
    const startTime = moment();
    let responseData = '';

    // Intercept the response
    const oldWrite = res.write;
    const oldEnd = res.end;

    res.write = function (chunk: any): boolean {
      responseData += chunk;

      return oldWrite.apply(res, arguments);
    };

    res.end = function (chunk: any): Response {
      if (chunk) {
        responseData += chunk;
      }

      const result = oldEnd.apply(res, arguments);

      return result;
    };

    res.on('finish', () => {
      const endTime = moment();
      const resTime = endTime.diff(startTime);

      // Create and save log entry
      const logEntry = new ApiLog();
      logEntry.header = JSON.stringify(req.headers);
      logEntry.url = req.path;
      logEntry.response_code = res.statusCode.toString();
      logEntry.response_time = resTime.toString();
      logEntry.form_data = JSON.stringify(req.body);
      logEntry.response_body = JSON.stringify(responseData);

      this.logRepository.save(logEntry);
    });

    next();
  }
}
