Files
TeleWave/backend/src/TeleWave.Application/Library/Interstitials/ListInterstitialBlocks/ListInterstitialBlocksQueryHandler.cs
T

56 lines
2.3 KiB
C#

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<ListInterstitialBlocksQuery, IReadOnlyList<InterstitialBlockDto>>
{
public async Task<IReadOnlyList<InterstitialBlockDto>> 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();
}
}