// Tiny fetch wrapper for /api/admin/*. Always credentials:'include' so the
// shared ws_actor cookie travels even on the admin subdomain.
const API = {
  async get(path, qs) {
    let url = path;
    if (qs && Object.keys(qs).length) {
      const usp = new URLSearchParams();
      Object.entries(qs).forEach(([k, v]) => {
        if (v === undefined || v === null || v === '') return;
        usp.set(k, String(v));
      });
      url += '?' + usp.toString();
    }
    const r = await fetch(url, { credentials: 'include' });
    if (!r.ok) throw await asError(r);
    return r.json();
  },
  async post(path, body) {
    const r = await fetch(path, {
      method: 'POST',
      credentials: 'include',
      headers: { 'Content-Type': 'application/json' },
      body: body == null ? undefined : JSON.stringify(body),
    });
    if (!r.ok) throw await asError(r);
    return r.json();
  },
};

async function asError(r) {
  let msg = `HTTP ${r.status}`;
  try {
    const j = await r.json();
    if (j?.error) msg = j.error;
    else if (j?.message) msg = j.message;
  } catch (_e) { /* ignore */ }
  const e = new Error(msg);
  e.status = r.status;
  return e;
}

window.API = API;

// ── Format helpers ──────────────────────────────────────────────
function fmtNum(n) {
  if (n == null) return '—';
  if (n >= 1e6) return (n / 1e6).toFixed(1).replace(/\.0$/, '') + 'M';
  if (n >= 1e3) return (n / 1e3).toFixed(1).replace(/\.0$/, '') + 'k';
  return String(n);
}
function fmtBytes(n) {
  if (n == null) return '—';
  if (n < 1024) return n + ' B';
  if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB';
  if (n < 1024 * 1024 * 1024) return (n / (1024 * 1024)).toFixed(1) + ' MB';
  return (n / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
}
function fmtDate(s) {
  if (!s) return '—';
  const d = new Date(s);
  return d.toLocaleDateString('es-MX', { day: '2-digit', month: 'short', year: 'numeric' });
}
function fmtDateTime(s) {
  if (!s) return '—';
  const d = new Date(s);
  return d.toLocaleString('es-MX', { day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit' });
}
function fmtAgo(s) {
  if (!s) return '—';
  const t = new Date(s).getTime();
  const ms = Date.now() - t;
  const sec = Math.floor(ms / 1000);
  if (sec < 60) return 'hace ' + sec + 's';
  const min = Math.floor(sec / 60);
  if (min < 60) return 'hace ' + min + ' min';
  const hr = Math.floor(min / 60);
  if (hr < 24) return 'hace ' + hr + ' h';
  const day = Math.floor(hr / 24);
  if (day < 30) return 'hace ' + day + ' d';
  const mo = Math.floor(day / 30);
  if (mo < 12) return 'hace ' + mo + ' meses';
  const yr = Math.floor(mo / 12);
  return 'hace ' + yr + ' año' + (yr === 1 ? '' : 's');
}
window.F = { num: fmtNum, bytes: fmtBytes, date: fmtDate, dateTime: fmtDateTime, ago: fmtAgo };
