/**
 * HTTPError — error HTTP con status code.
 * Lanzado por fetchJSON cuando la respuesta no es ok.
 */
export class HTTPError extends Error {
  constructor(public status: number, message: string) {
    super(message);
    this.name = "HTTPError";
  }
}

/**
 * fetchJSON — wrapper de fetch que parsea JSON, lanza HTTPError en errores HTTP
 * y retorna undefined en 204 No Content.
 *
 * URL final: `${baseUrl ?? ""}${path}`.
 * Headers default: `{ "Content-Type": "application/json" }`, mergeables via init.headers.
 * credentials: "include" por defecto, sobreescribible via init.
 */
export async function fetchJSON<T>(
  path: string,
  init?: RequestInit,
  baseUrl?: string,
): Promise<T> {
  const res = await fetch(`${baseUrl ?? ""}${path}`, {
    credentials: "include",
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...(init?.headers ?? {}),
    },
  });

  if (!res.ok) {
    const err = await res.json().catch(() => ({ Message: res.statusText }));
    throw new HTTPError(
      res.status,
      err.Message ?? err.message ?? res.statusText,
    );
  }

  if (res.status === 204) return undefined as T;
  return res.json() as Promise<T>;
}
