#!/usr/bin/env node
import { loadConfig } from "./config.mjs";
import { EdgeState } from "./state.mjs";
import { flushAccounting, sendHeartbeat, synchronize } from "./cloud.mjs";
import { createRadiusServers } from "./radius.mjs";
import { collectVpnTelemetry } from "./vpn.mjs";

const config = loadConfig();
const state = new EdgeState(config.stateDir);
await state.load();
const radius = createRadiusServers(config, state);
await radius.listen();

let stopped = false;
let timer;
let lastHeartbeatAt = 0;
async function cloudCycle() {
  if (stopped) return;
  try {
    const grants = await synchronize(config, state);
    const events = await flushAccounting(config, state);
    if (Date.now() - lastHeartbeatAt >= config.heartbeatIntervalMs) {
      try {
        const vpn = await collectVpnTelemetry(config);
        await sendHeartbeat(config, vpn, state);
        lastHeartbeatAt = Date.now();
      } catch (error) {
        console.warn(`Health telemetry unavailable: ${error.message}`);
      }
    }
    console.info(`Cloud sync healthy: ${grants} active grants, ${events} accounting events uploaded`);
  } catch (error) {
    state.pruneExpired();
    await state.save();
    console.warn(`Cloud sync unavailable; using unexpired local leases: ${error.message}`);
  } finally {
    if (!stopped) timer = setTimeout(cloudCycle, config.syncIntervalMs);
  }
}

async function shutdown(signal) {
  if (stopped) return;
  stopped = true;
  clearTimeout(timer);
  radius.close();
  await state.save();
  console.info(`Vimify Edge stopped after ${signal}`);
}

process.on("SIGINT", () => shutdown("SIGINT"));
process.on("SIGTERM", () => shutdown("SIGTERM"));

console.info(`Vimify Edge started for hotspot ${config.hotspotId}`);
await cloudCycle();
