import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";
import {
  decodeDevToken,
  handleDevOnboarding,
  shouldFallbackToDevMock,
} from "@/lib/dev-api-mock";
import { AUTH_COOKIE_NAME } from "@/lib/auth-cookie";
import { apiErrorResponse } from "@/lib/api-errors";
import { clearCookieOnUnauthorized, rejectLegacyAuthToken } from "@/lib/auth-proxy";
import { getOrCreateCorrelationId, withCorrelationId } from "@/lib/correlation-id";
import { fetchUpstream, type UpstreamOptions } from "@/lib/proxy-upstream";

async function proxyRequest(req: NextRequest, subPath: string) {
  const correlationId = getOrCreateCorrelationId(req);
  const jar = await cookies();
  const token = jar.get(AUTH_COOKIE_NAME)?.value;

  if (!token) {
    return apiErrorResponse(401, "UNAUTHORIZED", "Unauthorized", correlationId);
  }

  const legacyReject = rejectLegacyAuthToken(token, correlationId);
  if (legacyReject) return legacyReject;

  const headers: Record<string, string> = {
    "Content-Type": "application/json",
    Authorization: `Bearer ${token}`,
  };

  const fetchOptions: UpstreamOptions = { method: req.method, headers, correlationId };

  let bodyText = "";
  if (req.method !== "GET" && req.method !== "HEAD" && req.method !== "DELETE") {
    bodyText = await req.text();
    fetchOptions.body = bodyText;
  }

  if (shouldFallbackToDevMock()) {
    const user = decodeDevToken(token);
    if (!user) {
      return apiErrorResponse(401, "UNAUTHORIZED", "Unauthorized", correlationId);
    }
    const body = bodyText ? JSON.parse(bodyText) : null;
    const result = handleDevOnboarding(subPath, req.method, body, user.id, false);

    if (result.status === 204) {
      return withCorrelationId(new NextResponse(null, { status: 204 }), correlationId);
    }

    return withCorrelationId(NextResponse.json(result.data, { status: result.status }), correlationId);
  }

  const upstream = await fetchUpstream(`/onboarding/${subPath}`, fetchOptions);

  if (!upstream && shouldFallbackToDevMock()) {
    const user = decodeDevToken(token);
    if (!user) {
      return apiErrorResponse(401, "UNAUTHORIZED", "Unauthorized", correlationId);
    }
    const body = bodyText ? JSON.parse(bodyText) : null;
    const result = handleDevOnboarding(subPath, req.method, body, user.id, false);

    if (result.status === 204) {
      return withCorrelationId(new NextResponse(null, { status: 204 }), correlationId);
    }

    return withCorrelationId(NextResponse.json(result.data, { status: result.status }), correlationId);
  }

  if (!upstream) {
    return apiErrorResponse(
      503,
      "SERVICE_UNAVAILABLE",
      "Backend service unavailable",
      correlationId,
    );
  }

  if (upstream.status === 204) {
    return withCorrelationId(new NextResponse(null, { status: 204 }), correlationId);
  }

  const data = await upstream.json().catch(() => ({}));
  const response = withCorrelationId(NextResponse.json(data, { status: upstream.status }), correlationId);
  return clearCookieOnUnauthorized(response, upstream.status);
}

export async function GET(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
  const { path } = await params;
  return proxyRequest(req, path.join("/"));
}

export async function POST(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
  const { path } = await params;
  return proxyRequest(req, path.join("/"));
}

export async function PATCH(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
  const { path } = await params;
  return proxyRequest(req, path.join("/"));
}

export async function DELETE(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
  const { path } = await params;
  return proxyRequest(req, path.join("/"));
}
