import { getSessionAccessToken, verifySession } from '@/lib/auth/dal';
import { backendFetchStream } from '@/lib/http/backend-fetch';

/**
 * 게시판 첨부파일 다운로드 — 백엔드 파일을 브라우저로 중계한다.
 *
 * 왜 라우트 핸들러인가: 브라우저는 백엔드를 직접 호출하지 않는다(설계서 §7 BFF 전제). 백엔드 파일
 * API는 토큰을 요구하는데 그 토큰은 httpOnly 세션 안에만 있어 브라우저가 꺼낼 수 없다. 학생 회원
 * 엑셀 다운로드와 같은 구조다.
 *
 * 본문은 파싱하지 않고 업스트림 스트림을 그대로 흘려보낸다(서버 메모리에 파일 전체를 올리지
 * 않는다). 파일명·MIME도 백엔드 헤더를 그대로 전달한다.
 */

const FILE_DOWNLOAD_PATH = '/api/v1/common/file/download';
const DOWNLOAD_FAILED_MESSAGE =
  '첨부파일을 내려받지 못했습니다. 잠시 후 다시 시도해 주세요.';
const DOWNLOAD_TIMEOUT_MS = 60_000;

export async function GET(request: Request) {
  // 라우트 핸들러는 UI를 거치지 않고 직접 호출될 수 있으므로 여기서 직접 인증을 확인한다.
  await verifySession();

  const url = new URL(request.url);
  const attachmentId = url.searchParams.get('atchFileId');
  if (!attachmentId) {
    return new Response('첨부파일 식별자가 없습니다.', {
      status: 400,
      headers: { 'Content-Type': 'text/plain; charset=utf-8' },
    });
  }

  // 백엔드는 파일 일련번호(fileSn)로 개별 파일을 지목한다. 게시판은 파일 하나만 붙이므로 1이
  // 기본이며, 여러 개를 붙이게 되면 호출부가 번호를 넘긴다.
  const fileSn = url.searchParams.get('fileSn') ?? '1';

  const accessToken = await getSessionAccessToken();

  const result = await backendFetchStream(FILE_DOWNLOAD_PATH, {
    query: { atchFileId: attachmentId, fileSn },
    accessToken: accessToken ?? undefined,
    timeoutMs: DOWNLOAD_TIMEOUT_MS,
  });

  if (!result.ok) {
    // 실패 사유는 backendFetchStream이 서버 콘솔에 남긴다. 화면에는 일반화된 문구만 내보낸다.
    return new Response(DOWNLOAD_FAILED_MESSAGE, {
      status: 502,
      headers: { 'Content-Type': 'text/plain; charset=utf-8' },
    });
  }

  const upstream = result.data;

  return new Response(upstream.body, {
    status: 200,
    headers: {
      'Content-Type':
        upstream.headers.get('content-type') ?? 'application/octet-stream',
      'Content-Disposition':
        upstream.headers.get('content-disposition') ?? 'attachment',
    },
  });
}
