import { NextRequest } from "next/server";

import {
  clearAuthCookie,
  getAccessToken,
  getHermesUrl,
  hermesJsonResponse,
  unauthorizedResponse,
  upstreamConfigurationErrorResponse,
  upstreamUnavailableResponse,
} from "@/lib/server/hermes";

export async function proxyHermesRequest(
  request: NextRequest,
  path: string,
) {
  const token = await getAccessToken();

  if (!token) {
    return unauthorizedResponse();
  }

  const hermesUrl = getHermesUrl();

  if (!hermesUrl) {
    return upstreamConfigurationErrorResponse();
  }

  let hermesResponse: Response;
  const isMultipart = request.headers.get("content-type")?.includes("multipart/form-data") ?? false;
  const hasBody = request.method !== "GET" && request.method !== "DELETE";

  try {
    hermesResponse = await fetch(`${hermesUrl}${path}`, {
      method: request.method,
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: "application/json",
        ...(!isMultipart ? { "Content-Type": "application/json" } : {}),
      },
      body: !hasBody
        ? undefined
        : isMultipart
          ? await request.formData()
          : await request.text(),
      cache: "no-store",
    });
  } catch {
    return upstreamUnavailableResponse();
  }

  if (hermesResponse.status === 401) {
    const response = await hermesJsonResponse(hermesResponse);
    clearAuthCookie(response);
    return response;
  }

  return hermesJsonResponse(hermesResponse);
}

export async function proxyHermesStreamRequest(
  request: NextRequest,
  path: string,
) {
  const token = await getAccessToken();

  if (!token) {
    return unauthorizedResponse();
  }

  const hermesUrl = getHermesUrl();

  if (!hermesUrl) {
    return upstreamConfigurationErrorResponse();
  }

  let hermesResponse: Response;

  try {
    hermesResponse = await fetch(`${hermesUrl}${path}`, {
      method: request.method,
      headers: {
        Authorization: `Bearer ${token}`,
        Accept: request.headers.get("accept") ?? "*/*",
      },
      cache: "no-store",
    });
  } catch {
    return upstreamUnavailableResponse();
  }

  if (!hermesResponse.ok) {
    return hermesJsonResponse(hermesResponse);
  }

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