import { prisma } from '@hexahost/database';
import type { NodeSnapshot } from '@hexahost/scheduler';

function readMemoryField(
  payload: Record<string, unknown> | null | undefined,
  key: 'memoryTotalBytes' | 'memoryUsedBytes',
): number | null {
  const value = payload?.[key];
  return typeof value === 'number' ? value : null;
}

export async function loadNodeSnapshots(
  nodeIds?: string[],
): Promise<NodeSnapshot[]> {
  const nodes = await prisma.gameNode.findMany({
    where: nodeIds ? { id: { in: nodeIds } } : undefined,
    include: {
      allocations: {
        where: { status: 'ACTIVE' },
        select: { ramMbReserved: true },
      },
      heartbeats: {
        orderBy: { createdAt: 'desc' },
        take: 1,
        select: { payload: true },
      },
    },
  });

  return nodes.map((node) => {
    const heartbeatPayload = node.heartbeats[0]?.payload as
      | Record<string, unknown>
      | undefined;

    const reservedRamMb = node.allocations.reduce(
      (sum, allocation) => sum + allocation.ramMbReserved,
      0,
    );

    return {
      id: node.id,
      status: node.status,
      maxServers: node.maxServers,
      maxRamMb: node.maxRamMb,
      platformRamMb: node.platformRamMb,
      activeServers: node.activeServers,
      lastHeartbeatAt: node.lastHeartbeatAt,
      memoryTotalBytes: readMemoryField(heartbeatPayload, 'memoryTotalBytes'),
      memoryUsedBytes: readMemoryField(heartbeatPayload, 'memoryUsedBytes'),
      reservedRamMb,
      activeAllocationCount: node.allocations.length,
    };
  });
}

export async function loadNodeSnapshot(nodeId: string): Promise<NodeSnapshot | null> {
  const snapshots = await loadNodeSnapshots([nodeId]);
  return snapshots[0] ?? null;
}
