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

/**
 * 큰 파일 업로드 중계 — 브라우저 → 이 라우트 → 백엔드로 본문을 그대로 흘려보낸다.
 *
 * Server Action을 쓰지 않는 이유는 그 경로의 multipart가 10MB 부근에서 잘리기 때문이다
 * (`MAX_ATTACHMENT_BYTES` 주석). 브라우저가 백엔드를 직접 부를 수는 없다 — 토큰이 httpOnly
 * 세션 안에만 있어서 여기서 붙여 준다.
 *
 * 크기를 여기서 막지 않는다(사용자 확정). 본문을 버퍼에 담지 않고 그대로 흘려보내므로 이
 * 라우트에는 상한이 필요 없고, 실제 한도는 앞단 프록시와 백엔드가 정한다 — 넘으면 413이
 * 사유와 함께 화면까지 올라간다.
 */

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, '요청 형식이 올바르지 않습니다.');
  }

  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) {
    // 프록시가 자른 413은 크기 문제라 사용자에게 그대로 보인다. 나머지는 중계 실패다.
    return fail(result.code === 413 ? 413 : 502, result.message);
  }

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

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