import { api } from "@/convex/_generated/api" import { RETENTION_POLICY, RETENTION_STRATEGY } from "@/lib/retention" import { prisma } from "@/lib/prisma" import { createConvexClient } from "@/server/convex-client" import { env } from "@/lib/env" const OPEN_TICKET_STATUSES = ["PENDING", "AWAITING_ATTENDANCE", "PAUSED"] type DeviceHealth = { machines: number online: number warning: number offline: number withoutHeartbeat: number newestHeartbeatAgeMs: number | null oldestHeartbeatAgeMs: number | null thresholds: { offlineMs: number staleMs: number } truncated: boolean } export type HealthSnapshot = { generatedAt: string tickets: { total: number open: number last7d: number last24h: number } accounts: { users: number companies: number } devices: DeviceHealth | null retention: typeof RETENTION_POLICY retentionStrategy: typeof RETENTION_STRATEGY notes?: string } function toIsoString(date: Date) { return date.toISOString() } export async function getHealthSnapshot(): Promise { const now = new Date() const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000) const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000) const [totalTickets, openTickets, lastWeekTickets, lastDayTickets, userCount, companyCount] = await Promise.all([ prisma.ticket.count(), prisma.ticket.count({ where: { status: { in: OPEN_TICKET_STATUSES } } }), prisma.ticket.count({ where: { createdAt: { gte: sevenDaysAgo } } }), prisma.ticket.count({ where: { createdAt: { gte: oneDayAgo } } }), prisma.user.count(), prisma.company.count(), ]) let devices: DeviceHealth | null = null try { const client = createConvexClient() const convexHealth = await client.query(api.ops.healthSnapshot, { token: env.INTERNAL_HEALTH_TOKEN ?? env.REPORTS_CRON_SECRET ?? undefined, }) devices = { machines: convexHealth.totals.machines, online: convexHealth.connectivity.online, warning: convexHealth.connectivity.warning, offline: convexHealth.connectivity.offline, withoutHeartbeat: convexHealth.totals.withoutHeartbeat, newestHeartbeatAgeMs: convexHealth.heartbeatAgeMs.newest, oldestHeartbeatAgeMs: convexHealth.heartbeatAgeMs.oldest, thresholds: convexHealth.thresholds, truncated: convexHealth.totals.truncated, } } catch (error) { console.error("[health] Falha ao carregar estado das maquinas", error) } return { generatedAt: toIsoString(now), tickets: { total: totalTickets, open: openTickets, last7d: lastWeekTickets, last24h: lastDayTickets, }, accounts: { users: userCount, companies: companyCount, }, devices, retention: RETENTION_POLICY, retentionStrategy: RETENTION_STRATEGY, notes: devices ? undefined : "Convex nao respondeu; verificar conectividade ou token interno.", } }