import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';

export interface RequestLog {
  method: string;
  url: string;
  statusCode: number;
  responseTime: number;
  requestId: string;
  userAgent?: string;
  clientIp: string;
  requestIdHeader?: string;
}

export async function loggingMiddleware(fastify: FastifyInstance) {
  // Generate request ID if not present
  fastify.addHook('onRequest', (request: FastifyRequest, reply: FastifyReply, done) => {
    const requestId =
      request.headers['x-request-id'] ||
      request.headers['x-correlation-id'] ||
      `req-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;

    request.headers['x-request-id'] = requestId;
    (request as any).requestId = requestId;

    done();
  });

  // Log request start
  fastify.addHook('onRequest', (request: FastifyRequest, reply: FastifyReply) => {
    fastify.log.info({
      event: 'request_start',
      method: request.method,
      url: request.url,
      requestId: (request as any).requestId,
      userAgent: request.headers['user-agent'],
      clientIp: request.ip || request.headers['x-forwarded-for'] || 'unknown',
    });
  });

  // Log response
  fastify.addHook('onResponse', (request: FastifyRequest, reply: FastifyReply, done) => {
    const log: RequestLog = {
      method: request.method,
      url: request.url,
      statusCode: reply.statusCode,
      responseTime: reply.elapsedTime,
      requestId: (request as any).requestId,
      userAgent: request.headers['user-agent'],
      clientIp: request.ip || request.headers['x-forwarded-for'] || 'unknown',
      requestIdHeader: request.headers['x-request-id'] as string,
    };

    // Log based on status code
    if (reply.statusCode < 300) {
      fastify.log.info(log);
    } else if (reply.statusCode < 400) {
      fastify.log.warn(log);
    } else if (reply.statusCode < 500) {
      fastify.log.warn(log);
    } else {
      fastify.log.error(log);
    }

    done();
  });
}
