function headers(config) {
  return { authorization: `Bearer ${config.edgeToken}`, "x-vimify-edge-device": config.edgeDeviceId, "content-type": "application/json" };
}

async function readJson(response) {
  const body = await response.json().catch(() => null);
  if (!response.ok || !body?.ok) throw new Error(body?.error || `Cloud request failed with HTTP ${response.status}`);
  return body;
}

export async function synchronize(config, state) {
  const url = new URL("/api/v1/edge/sync", config.cloudUrl);
  url.searchParams.set("hotspot", config.hotspotId);
  url.searchParams.set("since", String(state.data.cursor));
  const response = await fetch(url, { headers: headers(config), signal: AbortSignal.timeout(10_000) });
  const payload = await readJson(response);
  await state.applySync(payload, config.hotspotId);
  return payload.authorizations?.length || 0;
}

export async function flushAccounting(config, state) {
  const events = state.accountingBatch();
  if (!events.length) return 0;
  const response = await fetch(new URL("/api/v1/edge/accounting", config.cloudUrl), {
    method: "POST",
    headers: headers(config),
    body: JSON.stringify({ events }),
    signal: AbortSignal.timeout(10_000),
  });
  const payload = await readJson(response);
  const accepted = Math.min(events.length, Number(payload.accepted) || 0);
  if (accepted) await state.acknowledgeAccounting(accepted);
  return accepted;
}

export async function sendHeartbeat(config, vpn, state) {
  const response = await fetch(new URL("/api/v1/edge/heartbeat", config.cloudUrl), {
    method: "POST",
    headers: headers(config),
    body: JSON.stringify({
      version: 1,
      radius: { state: "listening", queuedAccounting: state.accountingBatch().length },
      vpn,
    }),
    signal: AbortSignal.timeout(10_000),
  });
  return readJson(response);
}
