/**
 * File Response Builder
 *
 * Builds a NextResponse for streaming a file from storage.
 * Encapsulates all file-serving semantics — MIME type rendering policy,
 * Content-Disposition rules, security headers — in one place so the
 * generic route handler stays agnostic about storage concerns.
 *
 * Policy:
 *   - Image MIME types are served inline (required for <img> tags).
 *   - All other types force a download to prevent in-browser rendering
 *     of potentially dangerous content.
 *   - Content-Disposition is always emitted explicitly; omitting it leaves
 *     rendering decisions to browser heuristics, which vary by content-type
 *     and browser version.
 */

import { NextResponse } from 'next/server';

// MIME types that are safe to render inline (used in <img> tags).
// All other types are forced to download.
const INLINE_MIME_TYPES = new Set([
  'image/jpeg', 'image/png', 'image/gif', 'image/webp',
]);

/**
 * Build a NextResponse that streams a file from a storage result envelope.
 *
 * @param {{ body: *, contentType?: string, contentLength?: number, lastModified?: Date, filename?: string }} file
 * @returns {NextResponse}
 */
export function buildFileResponse(file) {
  const contentType = file.contentType || 'application/octet-stream';

  const headers = {
    'Content-Type': contentType,
    'Cache-Control': 'private, max-age=3600',
    'Last-Modified': file.lastModified?.toUTCString() ?? new Date().toUTCString(),
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'DENY',
  };

  if (file.contentLength != null) {
    headers['Content-Length'] = String(file.contentLength);
  }

  if (INLINE_MIME_TYPES.has(contentType)) {
    headers['Content-Disposition'] = 'inline';
  } else if (file.filename) {
    const encoded = encodeURIComponent(file.filename);
    headers['Content-Disposition'] = `attachment; filename="${encoded}"; filename*=UTF-8''${encoded}`;
  } else {
    headers['Content-Disposition'] = 'attachment';
  }

  return new NextResponse(file.body, { status: 200, headers });
}
