import { ConvexError, v } from "convex/values"

import { query } from "./_generated/server"
import { getOfflineThresholdMs, getStaleThresholdMs } from "./machines"

const MACHINE_SCAN_LIMIT = 1200

export const healthSnapshot = query({
  args: {
    token: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const requiredToken = process.env["INTERNAL_HEALTH_TOKEN"] ?? process.env["REPORTS_CRON_SECRET"] ?? null
    if (requiredToken && args.token !== requiredToken) {
      throw new ConvexError("Nao autorizado")
    }

    const now = Date.now()
    const offlineMs = getOfflineThresholdMs()
    const staleMs = getStaleThresholdMs(offlineMs)

    const machines = await ctx.db.query("machines").take(MACHINE_SCAN_LIMIT)
    const heartbeats = await ctx.db.query("machineHeartbeats").collect()

    let online = 0
    let warning = 0
    let offline = 0
    let newest = 0
    let oldest = 0
    const withHeartbeat = new Set<string>()

    for (const hb of heartbeats) {
      const ageMs = now - hb.lastHeartbeatAt
      withHeartbeat.add(String(hb.machineId))
      if (newest === 0 || hb.lastHeartbeatAt > newest) {
        newest = hb.lastHeartbeatAt
      }
      if (oldest === 0 || hb.lastHeartbeatAt < oldest) {
        oldest = hb.lastHeartbeatAt
      }
      if (ageMs <= offlineMs) {
        online += 1
      } else if (ageMs <= staleMs) {
        warning += 1
      } else {
        offline += 1
      }
    }

    const withoutHeartbeat = machines.length - withHeartbeat.size
    const totalOffline = offline + (withoutHeartbeat > 0 ? withoutHeartbeat : 0)

    return {
      totals: {
        machines: machines.length,
        heartbeats: heartbeats.length,
        withoutHeartbeat: withoutHeartbeat > 0 ? withoutHeartbeat : 0,
        truncated: machines.length === MACHINE_SCAN_LIMIT,
      },
      connectivity: {
        online,
        warning,
        offline: totalOffline,
      },
      heartbeatAgeMs: {
        newest: newest ? now - newest : null,
        oldest: oldest ? now - oldest : null,
      },
      thresholds: {
        offlineMs,
        staleMs,
      },
      generatedAt: now,
    }
  },
})
