import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";
import { handleDevDocumentUpload, shouldFallbackToDevMock } from "@/lib/dev-api-mock";
import { apiErrorResponse } from "@/lib/api-errors";
import { getOrCreateCorrelationId, withCorrelationId } from "@/lib/correlation-id";
import { fetchUpstream } from "@/lib/proxy-upstream";

const COOKIE_NAME = "agnet_token";
const MAX_SIZE = 10 * 1024 * 1024; // 10MB

export async function POST(req: NextRequest) {
  const correlationId = getOrCreateCorrelationId(req);
  const jar = await cookies();
  const token = jar.get(COOKIE_NAME)?.value;

  if (!token) {
    return apiErrorResponse(401, "UNAUTHORIZED", "Unauthorized", correlationId);
  }

  const formData = await req.formData();
  const sessionId = formData.get("sessionId") as string;
  const docType = formData.get("docType") as string;
  const file = formData.get("file") as File | null;

  if (!sessionId || !docType || !file) {
    return apiErrorResponse(
      400,
      "BAD_REQUEST",
      "sessionId, docType, and file are required",
      correlationId,
    );
  }

  if (file.size > MAX_SIZE) {
    return apiErrorResponse(
      413,
      "PAYLOAD_TOO_LARGE",
      "File exceeds 10MB limit",
      correlationId,
    );
  }

  if (shouldFallbackToDevMock()) {
    const mockResult = handleDevDocumentUpload(token, sessionId, docType, file.name);
    if (mockResult.status === 200) {
      return withCorrelationId(
        NextResponse.json(mockResult.data, { status: mockResult.status }),
        correlationId,
      );
    }
    return withCorrelationId(
      NextResponse.json(mockResult.data, { status: mockResult.status }),
      correlationId,
    );
  }

  const upstream = await fetchUpstream(`/onboarding/${sessionId}/documents`, {
    method: "POST",
    headers: { Authorization: `Bearer ${token}` },
    body: formData,
    correlationId,
  });

  if (upstream?.ok) {
    const data = await upstream.json().catch(() => ({}));
    return withCorrelationId(NextResponse.json(data, { status: upstream.status }), correlationId);
  }

  const useLocalHandler = !upstream || upstream.status === 404;
  if (useLocalHandler) {
    if (shouldFallbackToDevMock()) {
      const mockResult = handleDevDocumentUpload(token, sessionId, docType, file.name);
      if (mockResult.status === 200) {
        return withCorrelationId(
          NextResponse.json(mockResult.data, { status: mockResult.status }),
          correlationId,
        );
      }
    }

    if (!upstream) {
      return apiErrorResponse(
        503,
        "SERVICE_UNAVAILABLE",
        "Backend service unavailable",
        correlationId,
      );
    }

    return apiErrorResponse(404, "NOT_FOUND", "Session not found", correlationId);
  }

  const data = await upstream.json().catch(() => ({}));
  return withCorrelationId(NextResponse.json(data, { status: upstream.status }), correlationId);
}
