using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;
using TeleWave.Domain.Programming;

namespace TeleWave.Application.Programming.Templates.Junctions;

/// <summary>Общее для всех команд стыка: загрузка шаблона и отметка правил эфира изменёнными.</summary>
internal static class JunctionLoader
{
    public static Task<JunctionTemplate?> LoadAsync(
        IAppDbContext dbContext,
        Guid junctionId,
        CancellationToken cancellationToken
    ) =>
        dbContext
            .JunctionTemplates.Include(j => j.Elements)
            .FirstOrDefaultAsync(j => j.Id == junctionId, cancellationToken);

    /// <summary>
    /// Правка стыка — правка правил эфира. Стык общий, поэтому изменёнными помечаются все шаблоны,
    /// которые на него ссылаются: иначе чужой канал молча поехал бы по новым врезкам без применения.
    /// </summary>
    public static async Task<Result> MarkTemplatesChangedAsync(
        IAppDbContext dbContext,
        Guid junctionId,
        CancellationToken cancellationToken
    )
    {
        var viaSlots = await dbContext
            .Slots.AsNoTracking()
            .Where(s => s.JunctionBetweenId == junctionId || s.JunctionAfterId == junctionId)
            .Join(
                dbContext.GridLayers.AsNoTracking(),
                slot => slot.LayerId,
                layer => layer.Id,
                (_, layer) => layer.TemplateId
            )
            .Distinct()
            .ToListAsync(cancellationToken);

        var templates = await dbContext
            .ScheduleTemplates.Where(t =>
                viaSlots.Contains(t.Id) || t.DefaultJunctionId == junctionId
            )
            .ToListAsync(cancellationToken);

        foreach (var template in templates)
            template.MarkChanged();

        return Result.Success();
    }
}
