import { getSessionAccessToken, verifySession } from '@/lib/auth/dal';
import { backendFetchUpload } from '@/lib/http/backend-fetch';
import {
  MAX_STREAM_UPLOAD_BYTES,
  findFileModule,
} from '@/lib/domain/file-module';

/**
 * 큰 파일 업로드 중계 — 브라우저 → 이 라우트 → 백엔드로 본문을 그대로 흘려보낸다.
 *
 * Server Action을 쓰지 않는 이유는 그 경로의 multipart가 10MB 부근에서 잘리기 때문이다
 * (`MAX_ATTACHMENT_BYTES` 주석). 브라우저가 백엔드를 직접 부를 수는 없다 — 토큰이 httpOnly
 * 세션 안에만 있어서 여기서 붙여 준다.
 */

const UPLOAD_PATH = '/api/v1/common/file/upload';

function fail(status: number, message: string): Response {
  return Response.json({ message }, { status });
}

export async function POST(request: Request) {
  await verifySession();

  const moduleId = new URL(request.url).searchParams.get('module') ?? '';
  const storage = findFileModule(moduleId);
  if (!storage) {
    return fail(400, '알 수 없는 저장소입니다.');
  }

  const contentType = request.headers.get('content-type') ?? '';
  if (!contentType.startsWith('multipart/form-data')) {
    return fail(400, '요청 형식이 올바르지 않습니다.');
  }

  const declaredLength = Number(request.headers.get('content-length') ?? '');
  if (Number.isFinite(declaredLength) && declaredLength > MAX_STREAM_UPLOAD_BYTES) {
    return fail(
      413,
      `${Math.floor(MAX_STREAM_UPLOAD_BYTES / 1_000_000)}MB 이하만 올릴 수 있습니다.`
    );
  }

  if (!request.body) {
    return fail(400, '파일이 없습니다.');
  }

  const accessToken = await getSessionAccessToken();

  const result = await backendFetchUpload<unknown>(
    `${UPLOAD_PATH}/${storage.id}`,
    {
      body: request.body,
      contentType,
      accessToken: accessToken ?? undefined,
    }
  );

  if (!result.ok) {
    return fail(502, result.message);
  }

  if (typeof result.data !== 'string' || result.data === '') {
    return fail(502, '업로드 응답에 파일 식별자가 없습니다.');
  }

  return Response.json({ id: result.data });
}
