using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Developers.ValueObject; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Developers.GlobalStats; internal sealed class Handler(IAppDbContext db) : IQueryHandler { private const int DefaultDays = 7; private const int MaxDays = 90; public async Task Handle(Query request, CancellationToken ct) { var days = Math.Clamp(request.Days <= 0 ? DefaultDays : request.Days, 1, MaxDays); var since = DateTime.UtcNow.AddDays(-days); var totalApps = await db.ApiApplication.CountAsync(ct); var activeApps = await db.ApiApplication.CountAsync(c => c.Status == ApplicationStatus.Active, ct); var pendingApps = await db.ApiApplication.CountAsync(c => c.Status == ApplicationStatus.Pending, ct); var totalPats = await db.ApiPersonalAccessToken.CountAsync(ct); var activePats = await db.ApiPersonalAccessToken.CountAsync(c => c.RevokedAt == null, ct); var daily = await db.ApiRequestLog .Where(c => c.RequestedAt >= since) .GroupBy(c => DateOnly.FromDateTime(c.RequestedAt)) .Select(g => new DailyStat( g.Key, g.Count(), g.Count(c => c.StatusCode >= 400) )) .OrderBy(c => c.Date) .ToListAsync(ct); return new Response(totalApps, activeApps, pendingApps, totalPats, activePats, daily); } }