const crypto = require("crypto");
const { normalizeErrorPayload } = require("../utils/http");

function generateRequestId() {
  if (typeof crypto.randomUUID === "function") {
    return crypto.randomUUID();
  }
  return crypto.randomBytes(16).toString("hex");
}

function isPlainObject(value) {
  return (
    value !== null &&
    typeof value === "object" &&
    !Array.isArray(value) &&
    Object.prototype.toString.call(value) === "[object Object]"
  );
}

function requestIdMiddleware(req, res, next) {
  const requestId = generateRequestId();

  req.request_id = requestId;
  res.locals.request_id = requestId;
  res.setHeader("X-Request-Id", requestId);

  const originalJson = res.json.bind(res);
  res.json = (payload) => {
    const normalizedPayload = normalizeErrorPayload(payload, res.statusCode);

    if (isPlainObject(normalizedPayload)) {
      if (normalizedPayload.request_id === undefined) {
        return originalJson({ ...normalizedPayload, request_id: requestId });
      }
      return originalJson(normalizedPayload);
    }

    return originalJson({
      data: normalizedPayload,
      request_id: requestId,
    });
  };

  next();
}

module.exports = requestIdMiddleware;
