using Microsoft.EntityFrameworkCore; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Common.Messaging; using PnvPanel.Application.Common.Models; using PnvPanel.Domain.Activation; using PnvPanel.Domain.Configs; using PnvPanel.Domain.Nodes; namespace PnvPanel.Application.Admin.Stats; public sealed class GetStatsQueryHandler(IAppDbContext dbContext, IIdentityService identityService) : IQueryHandler> { public async Task> Handle( GetStatsQuery query, CancellationToken cancellationToken ) { var userStats = await identityService.GetUserStatsAsync(cancellationToken); var pendingActivations = await dbContext.ActivationRequests.CountAsync( r => r.Status == ActivationStatus.Pending, cancellationToken ); var totalNodes = await dbContext.Nodes.CountAsync(cancellationToken); var onlineNodes = await dbContext.Nodes.CountAsync( n => n.Status == NodeStatus.Online, cancellationToken ); var totalConfigs = await dbContext.VpnConfigs.CountAsync(cancellationToken); var activeConfigs = await dbContext.VpnConfigs.CountAsync( c => c.Status == ConfigStatus.Active, cancellationToken ); var trafficTotals = await dbContext .VpnConfigs.GroupBy(_ => 1) .Select(g => new { Up = g.Sum(c => c.UsedUpBytes), Down = g.Sum(c => c.UsedDownBytes) }) .FirstOrDefaultAsync(cancellationToken); return Result.Success( new StatsDto( userStats.Total, userStats.Activated, pendingActivations, totalNodes, onlineNodes, totalConfigs, activeConfigs, trafficTotals?.Up ?? 0, trafficTotals?.Down ?? 0 ) ); } }