import { db } from "@/db/client";
import { agentHeartbeats } from "@/db/schema";

// How long an agent may stay silent before its storage is treated as
// unreachable. Agents are expected to report well inside this window.
export const AGENT_TIMEOUT_SECONDS = Number.parseInt(
  process.env.AMPELOS_AGENT_TIMEOUT_SECONDS ?? "300",
  10,
);

export type AgentStatus = {
  agent: string;
  hostname: string | null;
  version: string | null;
  lastSeenAt: Date;
  firstSeenAt: Date;
  details: unknown;
  online: boolean;
  secondsSinceSeen: number;
};

export function isFresh(lastSeenAt: Date, now = Date.now()) {
  return (now - lastSeenAt.getTime()) / 1000 < AGENT_TIMEOUT_SECONDS;
}

export async function getAgentStatuses(): Promise<AgentStatus[]> {
  const rows = await db.select().from(agentHeartbeats);
  const now = Date.now();

  return rows
    .map((row) => ({
      agent: row.agent,
      hostname: row.hostname,
      version: row.version,
      lastSeenAt: row.lastSeenAt,
      firstSeenAt: row.firstSeenAt,
      details: row.details,
      online: isFresh(row.lastSeenAt, now),
      secondsSinceSeen: Math.max(0, Math.round((now - row.lastSeenAt.getTime()) / 1000)),
    }))
    .sort((a, b) => a.agent.localeCompare(b.agent));
}

export function formatSince(seconds: number) {
  if (seconds < 60) return `${seconds}s ago`;
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
  return `${Math.floor(seconds / 86400)}d ago`;
}
