import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { getConfig } from "../config.js";
import { setNetwork } from "../cache.js";
import type { NetworkConfig } from "../types.js";

const execFileAsync = promisify(execFile);

async function pingCheck(target: string): Promise<{ online: boolean; latencyMs: number | null }> {
  try {
    const { stdout } = await execFileAsync("ping", ["-c", "1", "-W", "3", target], { timeout: 5000 });
    const match = stdout.match(/time[=<]([\d.]+)\s*ms/);
    const latency = match ? parseFloat(match[1]) : null;
    return { online: true, latencyMs: latency };
  } catch {
    return { online: false, latencyMs: null };
  }
}

async function collectNetworkCheck(check: NetworkConfig): Promise<void> {
  const now = new Date().toISOString();

  if (!check.target) {
    setNetwork({
      id: check.id,
      name: check.name,
      status: "unknown",
      latency_ms: null,
      type: check.type,
      last_checked: now,
    });
    return;
  }

  const result = await pingCheck(check.target);
  setNetwork({
    id: check.id,
    name: check.name,
    status: result.online ? "online" : "offline",
    latency_ms: result.latencyMs,
    type: check.type,
    last_checked: now,
  });
}

export async function collectAllNetwork(): Promise<void> {
  const config = getConfig();

  await Promise.allSettled(config.network.map((n) => collectNetworkCheck(n)));

  await Promise.allSettled(
    config.hosts.filter((h) => h.type === "ssh").map(async (host) => {
      const now = new Date().toISOString();
      const result = await pingCheck(host.ip);
      setNetwork({
        id: `lan-${host.id}`,
        name: `LAN → ${host.name}`,
        status: result.online ? "online" : "offline",
        latency_ms: result.latencyMs,
        type: "lan",
        last_checked: now,
      });
    })
  );
}
