import {
  json,
  type NextFunction,
  type Request,
  type RequestHandler,
  type Response,
} from 'express';

/** The one route that accepts a large body, and how large. */
export const VOICE_EXTRACT_PATH = '/api/voice/extract';
export const VOICE_BODY_LIMIT = '10mb';

/**
 * JSON body parsing for the whole app.
 *
 * Voice recordings are base64 JSON and pass Express's 100 kb default at roughly 20 seconds
 * of audio, so that one route needs a larger limit while every other endpoint keeps the
 * default — a large body should not become acceptable everywhere.
 *
 * Deliberately one middleware that *chooses* a parser, not a path-mounted parser stacked in
 * front of a default one: that arrangement depended on Express's mount-path stripping and on
 * body-parser skipping an already-parsed request, and silently stopped applying whenever the
 * middleware order shifted. One explicit branch has no such coupling.
 */
/**
 * Express routes case-insensitively and ignores exactly one trailing slash, so
 * `/API/Voice/Extract/` reaches the same controller and must get the same limit — otherwise
 * it 413s every real recording, which reads as a broken microphone rather than a route.
 * Two slashes never route, so they must not buy a 10 MB buffer either.
 */
function isVoiceExtractPath(path: string): boolean {
  return path.toLowerCase().replace(/\/$/, '') === VOICE_EXTRACT_PATH;
}

export function createJsonBodyParser(): RequestHandler {
  const voiceParser = json({ limit: VOICE_BODY_LIMIT });
  const defaultParser = json();

  return (req: Request, res: Response, next: NextFunction) =>
    isVoiceExtractPath(req.path)
      ? voiceParser(req, res, next)
      : defaultParser(req, res, next);
}
