using LiteCqrs; using Microsoft.EntityFrameworkCore; using TeleWave.Application.Common.Interfaces; using TeleWave.Domain.Library; namespace TeleWave.Application.Library.Interstitials.ListInterstitialBlocks; public sealed class ListInterstitialBlocksQueryHandler(IAppDbContext dbContext) : IQueryHandler> { public async Task> Handle( ListInterstitialBlocksQuery query, CancellationToken cancellationToken ) { var collections = await dbContext .Collections.AsNoTracking() .Include(c => c.Items) .OrderBy(c => c.Name) .ToListAsync(cancellationToken); // «Блок» — не отдельная сущность, а признак состава: коллекция целиком из роликов. Смешанные // коллекции (франшизы) остаются на своём экране и сюда не попадают. var showIds = collections.SelectMany(c => c.Items.Select(i => i.ShowId)).Distinct().ToList(); var clips = await dbContext .Shows.AsNoTracking() .Where(s => showIds.Contains(s.Id) && s.Kind == ShowKind.Interstitial) .Select(s => new { s.Id, AssetIds = s.Episodes.Select(e => e.MediaAssetId).ToList(), }) .ToDictionaryAsync(s => s.Id, s => s.AssetIds, cancellationToken); var assetIds = clips.Values.SelectMany(ids => ids).Distinct().ToList(); var durations = await dbContext .MediaAssets.AsNoTracking() .Where(a => assetIds.Contains(a.Id) && a.Duration != null) .Select(a => new { a.Id, a.Duration }) .ToDictionaryAsync(a => a.Id, a => a.Duration!.Value.TotalSeconds, cancellationToken); return collections .Where(c => c.Items.Count > 0 && c.Items.All(i => clips.ContainsKey(i.ShowId))) .Select(c => new InterstitialBlockDto( c.Id, c.Name, c.Items.Count, c.Items.Sum(i => clips[i.ShowId] .Sum(assetId => durations.TryGetValue(assetId, out var d) ? d : 0) ) )) .ToList(); } }