import { configuredBackendUrl } from "@/lib/backend-url"

export class ApiClientError extends Error {
  constructor(
    message: string,
    public readonly status: number,
    public readonly payload?: unknown,
  ) {
    super(message)
    this.name = "ApiClientError"
  }
}

function trimBaseUrl(baseUrl: string): string {
  return baseUrl.replace(/\/$/, "")
}

function resolveRequestUrl(baseUrl: string, path: string): string {
  if (path.startsWith("/") && configuredBackendUrl().kind === "same-origin") {
    return path
  }
  return trimBaseUrl(baseUrl) + path
}

export async function requestJson<T>(
  baseUrl: string,
  path: string,
  init?: RequestInit,
): Promise<T> {
  const hasBody = init?.body != null
  const res = await fetch(resolveRequestUrl(baseUrl, path), {
    ...init,
    headers: {
      ...(hasBody ? { "Content-Type": "application/json" } : {}),
      ...(init?.headers ?? {}),
    },
  })

  if (res.status === 204) return undefined as T

  const payload = await res.json().catch(() => undefined)
  if (!res.ok) {
    const msg =
      typeof payload === "object" &&
      payload !== null &&
      "error" in payload &&
      typeof (payload as { error?: unknown }).error === "string"
        ? (payload as { error: string }).error
        : res.statusText
    throw new ApiClientError(msg, res.status, payload)
  }

  return payload as T
}
