import { cookies } from "next/headers"
import { NextRequest, NextResponse } from "next/server"

const HOP_BY_HOP = new Set([
    "host",
    "connection",
    "content-length",
    "keep-alive",
    "transfer-encoding",
    "upgrade",
    "te",
    "trailer",
    "proxy-authorization",
    "proxy-authenticate",
])

async function forward(req: NextRequest, ctx: { params: Promise<{ path: string[] }> }) {
    const cookieStore = await cookies()
    const apiBase = cookieStore.get("api_base_url")?.value
    const wsUuid = cookieStore.get("workspace_uuid")?.value
    const token = cookieStore.get("auth_token")?.value

    if (!apiBase || !wsUuid) {
        return NextResponse.json(
            {
                message: "Workspace session not found. Please open your garage from the SaaS dashboard.",
                code: "workspace_session_missing",
            },
            { status: 412 },
        )
    }

    const { path } = await ctx.params
    const url = new URL(req.url)
    // The OpenAPI clients keep `/api/...` in their route patterns, so when the
    // client uses baseUrl=`/api/proxy` the resulting URL is
    // `/api/proxy/api/customers`. Forward the path verbatim and rejoin so the
    // upstream becomes `{apiBase}/api/customers`.
    const target = `${apiBase.replace(/\/$/, "")}/${(path ?? []).join("/")}${url.search}`

    const headers = new Headers()
    req.headers.forEach((value, key) => {
        if (!HOP_BY_HOP.has(key.toLowerCase()) && key.toLowerCase() !== "cookie") {
            headers.set(key, value)
        }
    })
    headers.set("Accept", "application/json")
    headers.set("X-Workspace-UUID", wsUuid)
    if (token) {
        headers.set("Authorization", `Bearer ${token}`)
    }

    const init: RequestInit = {
        method: req.method,
        headers,
        redirect: "manual",
    }

    if (req.method !== "GET" && req.method !== "HEAD") {
        init.body = await req.arrayBuffer()
    }

    let upstream: Response
    try {
        upstream = await fetch(target, init)
    } catch (err) {
        return NextResponse.json(
            {
                message: "Failed to reach garage backend.",
                code: "backend_unreachable",
                error: (err as Error).message,
            },
            { status: 502 },
        )
    }

    const respHeaders = new Headers()
    upstream.headers.forEach((value, key) => {
        const k = key.toLowerCase()
        if (HOP_BY_HOP.has(k) || k === "set-cookie") return
        respHeaders.set(key, value)
    })

    return new NextResponse(upstream.body, {
        status: upstream.status,
        statusText: upstream.statusText,
        headers: respHeaders,
    })
}

export const GET = forward
export const POST = forward
export const PUT = forward
export const PATCH = forward
export const DELETE = forward
export const OPTIONS = forward
export const HEAD = forward
