import createFetchClient, { Middleware } from "openapi-fetch"

import { ACCESS_TOKEN_REGEXP, API_URL } from "@shared/lib/constants"

import { paths } from "./__generated__/openapi.types"

const isServer = typeof window === "undefined"

const getAccessTokenFromCookieHeader = (
	cookieHeader: string | null,
): string | undefined => {
	if (!cookieHeader) return
	const token = cookieHeader.replace(ACCESS_TOKEN_REGEXP, "$1")
	return token.length ? token : undefined
}

export const fetchClient = createFetchClient<paths>({
	baseUrl: API_URL,
	// credentials: "include",
	headers: {
		"Content-Type": "application/json",
	},
})

const middleware: Middleware = {
	async onRequest({ request }) {
		if (request.headers.has("Authorization")) return

		let token: string | undefined
		if (isServer) {
			// In middleware/edge runtime there is no `next/headers` request scope.
			token = getAccessTokenFromCookieHeader(request.headers.get("cookie"))
			if (!token) {
				try {
					const { cookies } = await import("next/headers")
					token = (await cookies()).get("access_token")?.value
				} catch {
					// Not in a request scope (e.g. middleware/edge or build-time).
				}
			}
		} else {
			token = document.cookie.replace(ACCESS_TOKEN_REGEXP, "$1")
		}

		if (token?.length) request.headers.set("Authorization", `Bearer ${token}`)
	},
	async onError({ error }) {
		return new Error("Oops, fetch failed", { cause: error })
	},
}
fetchClient.use(middleware)
