// Server-side proxy helper for Next.js API routes.
// Forwards requests to the NestJS backend, including the Bearer token.

import { NextRequest, NextResponse } from "next/server";
import { ACCESS_COOKIE, NONCE_COOKIE } from "./auth-cookies";

const BASE_URL = process.env.LEDGERONE_API_URL ?? "http://localhost:3051";

export function getBackendUrl(path: string): string {
  return `${BASE_URL}/api/${path.replace(/^\//, "")}`;
}

interface ProxyOptions {
  method?: string;
  body?: BodyInit | null;
  extraHeaders?: Record<string, string>;
  search?: string;
}

export async function proxyRequest(
  req: NextRequest,
  backendPath: string,
  options: ProxyOptions = {}
): Promise<NextResponse> {
  const url = new URL(req.url);
  const search = options.search !== undefined ? options.search : url.search;
  const targetUrl = `${getBackendUrl(backendPath)}${search}`;

  const method = options.method ?? req.method;
  const auth = req.headers.get("authorization") ?? "";
  const cookieAccessToken = req.cookies.get(ACCESS_COOKIE)?.value ?? "";
  const sessionNonce = req.cookies.get(NONCE_COOKIE)?.value ?? "";
  const contentType = req.headers.get("content-type") ?? "";
  const userAgent = req.headers.get("user-agent") ?? "";
  const forwardedFor = req.headers.get("x-forwarded-for") ?? "";

  const headers: Record<string, string> = { ...options.extraHeaders };
  if (auth) headers["Authorization"] = auth;
  else if (cookieAccessToken) headers["Authorization"] = `Bearer ${cookieAccessToken}`;
  if (sessionNonce) headers["X-LedgerOne-Session-Nonce"] = sessionNonce;
  if (userAgent) headers["User-Agent"] = userAgent;
  if (forwardedFor) headers["X-Forwarded-For"] = forwardedFor;

  let body: BodyInit | null | undefined = undefined;

  if (method !== "GET" && method !== "HEAD") {
    if (options.body !== undefined) {
      body = options.body;
      if (contentType) headers["Content-Type"] = contentType;
    } else if (contentType.includes("multipart/form-data")) {
      body = await req.formData();
      // Do not set Content-Type — fetch sets it with boundary automatically
    } else {
      body = await req.text();
      if (contentType) headers["Content-Type"] = contentType;
    }
  }

  try {
    const res = await fetch(targetUrl, {
      method,
      headers,
      body: body ?? undefined,
    });
    const payload = await res.text();
    const response = new NextResponse(payload, {
      status: res.status,
      headers: {
        "Content-Type": res.headers.get("content-type") ?? "application/json",
      },
    });
    const nextNonce = res.headers.get("x-ledgerone-next-nonce");
    if (nextNonce) {
      response.cookies.set(NONCE_COOKIE, nextNonce, {
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        sameSite: "lax",
        path: "/",
        maxAge: 30 * 24 * 60 * 60,
      });
    }
    return response;
  } catch {
    return NextResponse.json(
      {
        data: null,
        meta: { timestamp: new Date().toISOString(), version: "v1" },
        error: { message: "Backend unavailable." },
      },
      { status: 503 }
    );
  }
}
