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 a single middleware that *chooses* a parser, rather than a path-mounted
 * parser stacked in front of a default one. That arrangement relied on Express's
 * mount-path stripping plus body-parser skipping an already-parsed request, and it
 * silently stopped applying when the surrounding middleware order shifted — at which point
 * the endpoint rejected every real recording with a 500. One explicit branch has no such
 * coupling, and is covered by body-parsers.spec.ts.
 */
/**
 * Express routes case-insensitively and ignores a trailing slash unless configured
 * otherwise, so `/API/Voice/Extract/` reaches the same controller. Matching only the
 * canonical spelling would hand those requests the 100 kb parser and 413 every real
 * recording — a failure that looks like a broken microphone, not a routing detail.
 */
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);
}
