using LiteCqrs; using Microsoft.EntityFrameworkCore; using TeleWave.Application.Common.Interfaces; using TeleWave.Domain.Library; namespace TeleWave.Application.Library.ListShows; public sealed class ListShowsQueryHandler(IAppDbContext dbContext) : IQueryHandler> { public async Task> Handle( ListShowsQuery query, CancellationToken cancellationToken ) { var source = dbContext .Shows.AsNoTracking() .Include(s => s.Episodes) .Include(s => s.Genres) // Серии и жанры — сиблинги: одним запросом это честное перемножение (сериал на 200 серий // с тремя жанрами даёт 600 строк вместо 203). Разделяем. .AsSplitQuery() .Where(s => query.Interstitials ? s.Kind == ShowKind.Interstitial : s.Kind != ShowKind.Interstitial ); var filtered = query.GenreId is { } genreId ? source.Where(s => s.Genres.Any(g => g.GenreId == genreId)) : source; var shows = await filtered.OrderBy(s => s.Name).ToListAsync(cancellationToken); // Названия только для основных жанров — в списке показывается один. var primaryIds = shows .Select(s => s.PrimaryGenreId) .Where(id => id is not null) .Select(id => id!.Value) .Distinct() .ToList(); var genreNames = await dbContext .Genres.AsNoTracking() .Where(g => primaryIds.Contains(g.Id)) .ToDictionaryAsync(g => g.Id, g => g.Name, cancellationToken); // Имена ассетов нужны, чтобы распознать сезоны (номера в модели не хранятся). var assetIds = shows .SelectMany(s => s.Episodes.Select(e => e.MediaAssetId)) .Distinct() .ToList(); var names = await dbContext .MediaAssets.AsNoTracking() .Where(a => assetIds.Contains(a.Id)) .Select(a => new { a.Id, a.OriginalFileName }) .ToDictionaryAsync(a => a.Id, a => a.OriginalFileName, cancellationToken); return shows .Select(s => { var seasons = s .Episodes.Select(e => names.TryGetValue(e.MediaAssetId, out var n) ? EpisodeName.ParseSeason(n) : null ) .Where(season => season is not null) .Distinct() .Count(); return new ShowSummaryDto( s.Id, s.Name, s.OriginalName, s.Kind, s.Audience, s.Episodes.Count, seasons, s.Year, s.PosterImageId is not null, s.CreatedAt, s.PrimaryGenreId is { } primaryId && genreNames.TryGetValue(primaryId, out var g) ? g : null ); }) .ToList(); } }