// Thin fetch wrapper. The cookie is sent automatically (same-origin) so
// we don't need to add auth headers. Every helper returns the parsed JSON
// body and throws an ApiError on non-2xx so callers can `try/catch`.

class ApiError extends Error {
  constructor(status, body) {
    super(body?.error || `HTTP ${status}`);
    this.status = status;
    this.body = body;
  }
}

async function call(method, path, body) {
  const res = await fetch("/api" + path, {
    method,
    credentials: "same-origin",
    headers: body ? { "Content-Type": "application/json" } : undefined,
    body: body ? JSON.stringify(body) : undefined,
  });
  const ct = res.headers.get("content-type") || "";
  const parsed = ct.includes("application/json") ? await res.json() : await res.text();
  if (!res.ok) throw new ApiError(res.status, parsed);
  return parsed;
}

const api = {
  get:    (p)      => call("GET",    p),
  post:   (p, b)   => call("POST",   p, b),
  patch:  (p, b)   => call("PATCH",  p, b),
  delete: (p, b)   => call("DELETE", p, b),

  // Multipart uploads (imagery). Field name should be 'file'.
  async upload(path, files) {
    const fd = new FormData();
    for (const f of files) fd.append("file", f);
    const res = await fetch("/api" + path, { method: "POST", credentials: "same-origin", body: fd });
    const j = await res.json();
    if (!res.ok) throw new ApiError(res.status, j);
    return j;
  },
};
window.api = api;
window.ApiError = ApiError;
