const ENV_API_BASE = (import.meta.env.VITE_API_BASE || "").trim();
const API_BASE_STORAGE_KEY = "chatapp_api_base";

function normalizeApiBase(value) {
  const s = String(value || "").trim();
  if (!s) return "";
  return s.endsWith("/") ? s.slice(0, -1) : s;
}

export function getApiBase() {
  try {
    const fromStorage = normalizeApiBase(localStorage.getItem(API_BASE_STORAGE_KEY) || "");
    return fromStorage || normalizeApiBase(ENV_API_BASE) || "";
  } catch {
    return normalizeApiBase(ENV_API_BASE) || "";
  }
}

export function setApiBase(base) {
  const normalized = normalizeApiBase(base);
  try {
    if (!normalized) localStorage.removeItem(API_BASE_STORAGE_KEY);
    else localStorage.setItem(API_BASE_STORAGE_KEY, normalized);
  } catch {
    // ignore
  }
  return normalized;
}

export class ApiError extends Error {
  constructor(message, { status = 0, code = "error", data = null } = {}) {
    super(message);
    this.name = "ApiError";
    this.status = status;
    this.code = code;
    this.data = data;
  }
}

function buildUrl(path) {
  const base = getApiBase();
  if (!path.startsWith("/")) path = `/${path}`;
  return `${base}${path}`;
}

async function readJsonSafe(res) {
  const ctype = res.headers.get("content-type") || "";
  if (!ctype.toLowerCase().includes("application/json")) return null;
  try {
    return await res.json();
  } catch {
    return null;
  }
}

function authHeaders(token) {
  return token ? { Authorization: `Bearer ${token}` } : {};
}

export async function api(path, { method = "GET", token = null, body = null, headers = {} } = {}) {
  const merged = { ...authHeaders(token), ...headers };
  let requestBody = undefined;
  if (body !== null) {
    merged["Content-Type"] = "application/json";
    requestBody = JSON.stringify(body);
  }

  const res = await fetch(buildUrl(path), {
    method,
    headers: merged,
    body: requestBody,
  });
  if (res.status === 204) return null;

  const data = (await readJsonSafe(res)) ?? {};
  if (!res.ok) {
    const code = data?.error?.code || "error";
    const msg = data?.error?.message || `HTTP ${res.status}`;
    throw new ApiError(msg, { status: res.status, code, data });
  }
  return data;
}

export async function apiFetch(path, { method = "GET", token = null, body = null, headers = {}, ...rest } = {}) {
  const merged = { ...authHeaders(token), ...headers };
  return fetch(buildUrl(path), { method, headers: merged, body, ...rest });
}

export async function apiBlob(path, { token = null, headers = {} } = {}) {
  const res = await apiFetch(path, { method: "GET", token, headers });
  if (!res.ok) {
    const data = (await readJsonSafe(res)) ?? {};
    const code = data?.error?.code || "error";
    const msg = data?.error?.message || `HTTP ${res.status}`;
    throw new ApiError(msg, { status: res.status, code, data });
  }
  return await res.blob();
}
