using LiteCqrs; using Microsoft.EntityFrameworkCore; using TeleWave.Application.Broadcast; using TeleWave.Application.Common.Interfaces; using TeleWave.Application.Common.Models; namespace TeleWave.Application.Programming.Templates.GetTemplate; public sealed class GetChannelTemplateQueryHandler(IAppDbContext dbContext) : IQueryHandler> { public async Task> Handle( GetChannelTemplateQuery query, CancellationToken cancellationToken ) { var channel = await dbContext .Channels.AsNoTracking() .FirstOrDefaultAsync(c => c.Id == query.ChannelId, cancellationToken); if (channel is null) return Result.Failure(ChannelErrors.NotFound); var template = await dbContext .ScheduleTemplates.AsNoTracking() .Include(t => t.Layers) .ThenInclude(l => l.Slots) .FirstOrDefaultAsync(t => t.ChannelId == channel.Id, cancellationToken); if (template is null) return Result.Failure(ChannelErrors.TemplateNotFound); // Имена групп резолвим одним запросом: инспектор слота показывает их сразу, без второго обхода. var groupIds = template .Layers.SelectMany(l => l.Slots) .Select(s => s.GroupId) .Where(id => id is not null) .Select(id => id!.Value) .Distinct() .ToList(); var groupNames = await dbContext .Groups.AsNoTracking() .Where(g => groupIds.Contains(g.Id)) .ToDictionaryAsync(g => g.Id, g => g.Name, cancellationToken); var layers = template .Layers.OrderByDescending(l => l.Priority) .Select(layer => new GridLayerDto( layer.Id, layer.Name, layer.Priority, layer.IsEnabled, layer.IsBackground, LayerApplicability.FromJson(layer.ApplicabilityJson), layer .Slots.OrderBy(s => s.Weekday ?? -1) .ThenBy(s => s.TargetStart) .Select(slot => new SlotDto( slot.Id, slot.LayerId, slot.Weekday, slot.TargetStart, slot.TargetDurationMinutes, slot.Title, slot.Daypart, slot.SlotKind, slot.GroupId, slot.GroupId is { } gid && groupNames.TryGetValue(gid, out var gname) ? gname : null, SlotStrategy.FromJson(slot.StrategyJson), RepeatSource.FromJson(slot.RepeatSourceJson), slot.BlockMode, slot.BlockValue, slot.OverflowPolicy, slot.IsAnchor, slot.MaxDriftMinutes, slot.SnapToMinutes, slot.JunctionBetweenId, slot.JunctionAfterId )) .ToList() )) .ToList(); return Result.Success( new ScheduleTemplateDto( template.Id, template.ChannelId, template.Name, template.FallbackGroupId, template.DefaultJunctionId, PlanningRules.FromJson(template.RulesJson), template.Revision, template.AppliedRevision, template.HasPendingChanges, channel.UtcOffsetMinutes, channel.DayStartTime, layers ) ); } }