import { env } from "@/lib/env";
import { UpdotAuthManager } from "@/lib/updot-auth";

/**
 * Forward one request to Core using the shared Updot admin session.
 *
 * The open `/v1/admin/*` proxy has no per-route guards, so anything that must
 * be access-controlled gets its own guarded route here instead and calls this.
 */
export async function forwardToUpdotCore(
  path: string,
  init: { method: string; body?: string } = { method: "GET" },
): Promise<Response> {
  const upstream = env.GetString("UPDOT_CORE_BASE_URL");
  if (!upstream) {
    return new Response(
      JSON.stringify({
        success: false,
        message: "Core base URL not configured",
      }),
      { status: 500, headers: { "content-type": "application/json" } },
    );
  }

  const authManager = UpdotAuthManager.getInstance();
  const upstreamUrl = new URL(path, upstream);

  const doRequest = async (session: {
    admin_session: string;
    admin_session_id: string;
  }) => {
    const headers = new Headers({
      Accept: "application/json",
      "Content-Type": "application/json",
      Cookie: [
        `kc_session=${session.admin_session}`,
        `kc_session_id=${session.admin_session_id}`,
        `__sstkn=${session.admin_session}`,
        `__ssid=${session.admin_session_id}`,
        `admin_session=${session.admin_session}`,
        `admin_session_id=${session.admin_session_id}`,
      ].join("; "),
      Origin: new URL(upstream).origin,
      Referer: `${new URL(upstream).origin}/`,
    });

    return await fetch(upstreamUrl.toString(), {
      method: init.method,
      headers,
      body: ["GET", "HEAD"].includes(init.method) ? undefined : init.body,
    });
  };

  let session = await authManager.getOrLogin();
  if (!session) {
    return new Response(
      JSON.stringify({ success: false, message: "Core authentication failed" }),
      { status: 502, headers: { "content-type": "application/json" } },
    );
  }

  let response = await doRequest(session);
  if ([401, 403].includes(response.status)) {
    authManager.invalidate();
    session = await authManager.getOrLogin();
    if (session) {
      response = await doRequest(session);
    }
  }

  const respHeaders = new Headers(response.headers);
  respHeaders.delete("content-encoding");
  respHeaders.delete("content-length");
  return new Response(response.body, {
    status: response.status,
    headers: respHeaders,
  });
}
