import type { NextFunction, Request, Response } from "express";
import { logger } from "../lib/logger.service.js";

/**
 * Logs one line per request once it finishes — method, path, status code,
 * and duration. Mounted first in `app.ts` (before every route, and before
 * the error handler) so it wraps the whole request/response cycle,
 * including requests that end in a 404 or an error response.
 *
 * Listens on `res`'s `"finish"` event rather than wrapping `next()` in a
 * `try`/`finally`: this middleware calls `next()` immediately and returns,
 * so it never itself sits on the stack waiting for the rest of the
 * pipeline to resolve — `"finish"` fires once Express has actually flushed
 * the response, whichever handler (or the error middleware) produced it.
 *
 * `4xx`/`5xx` responses log at `warn`/`error` respectively (status alone
 * decides the level — this middleware has no idea *why* a request failed,
 * just that it did); everything else logs at `info`. A route's own
 * handler/the error middleware may log more detail about *why* separately
 * (see `error-middleware` wiring in `app.ts`) — this line is just the
 * "a request happened, here's the outcome" operational trace.
 */
export function requestLogger(req: Request, res: Response, next: NextFunction): void {
  const startedAt = process.hrtime.bigint();

  res.on("finish", () => {
    const durationMs = Number(process.hrtime.bigint() - startedAt) / 1_000_000;
    const meta = {
      method: req.method,
      path: req.originalUrl,
      status: res.statusCode,
      durationMs: Math.round(durationMs * 100) / 100,
    };

    if (res.statusCode >= 500) {
      logger.error("Request completed", meta);
    } else if (res.statusCode >= 400) {
      logger.warn("Request completed", meta);
    } else {
      logger.info("Request completed", meta);
    }
  });

  next();
}
