using Microsoft.EntityFrameworkCore; using PowderCoating.Application.Interfaces; using PowderCoating.Infrastructure.Data; namespace PowderCoating.Infrastructure.Services; /// /// Implements by querying AiUsageLogs and /// QuotePhotos directly via ApplicationDbContext. Both tables either are /// not BaseEntity (AiUsageLog) or require cross-tenant GROUP BY aggregations that must /// execute in SQL; this service encapsulates those queries so the controller stays clean. /// public class AiUsageReportService : IAiUsageReportService { private readonly ApplicationDbContext _context; public AiUsageReportService(ApplicationDbContext context) { _context = context; } /// public async Task GetReportDataAsync() { var now = DateTime.UtcNow; var todayStart = now.Date; var last7Start = todayStart.AddDays(-7); var last30Start = todayStart.AddDays(-30); var usageByCompany = await _context.AiUsageLogs .GroupBy(l => l.CompanyId) .Select(g => new AiCompanyUsage( g.Key, g.Count(l => l.CalledAt >= todayStart), g.Count(l => l.CalledAt >= last7Start), g.Count(l => l.CalledAt >= last30Start), g.Count())) .ToListAsync(); var featureStats = await _context.AiUsageLogs .Where(l => l.CalledAt >= last30Start) .GroupBy(l => new { l.CompanyId, l.Feature }) .Select(g => new AiFeatureStat(g.Key.CompanyId, g.Key.Feature, g.Count())) .ToListAsync(); var photoCounts = await _context.QuotePhotos .IgnoreQueryFilters() .Where(p => p.IsAiAnalysisPhoto && !p.IsDeleted) .GroupBy(p => p.CompanyId) .Select(g => new { CompanyId = g.Key, Count = g.Count() }) .ToDictionaryAsync(x => x.CompanyId, x => x.Count); return new AiUsageReportData(usageByCompany, featureStats, photoCounts); } }