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

namespace TeleWave.Application.Programming.Groups;

/// <summary>
/// Снимает элемент со всех групп при его удалении из библиотеки. Нужен потому, что ссылка группы
/// полиморфна (шоу либо коллекция) и внешнего ключа под неё нет — каскад БД тут не сработает,
/// а висячая позиция при генерации развернулась бы в пустоту.
///
/// Затронутым группам пересчитывается статистика: иначе в инспекторе слота осталось бы обещание
/// эфира, которого больше нет.
/// </summary>
public sealed class GroupMembershipCleaner(IAppDbContext dbContext, GroupStatsService stats)
{
    public async Task RemoveElementAsync(
        GroupElementKind kind,
        Guid elementId,
        CancellationToken cancellationToken
    )
    {
        var affectedGroupIds = await dbContext
            .GroupItems.Where(i => i.ElementKind == kind && i.ElementId == elementId)
            .Select(i => i.GroupId)
            .Distinct()
            .ToListAsync(cancellationToken);

        if (affectedGroupIds.Count == 0)
            return;

        var groups = await dbContext
            .Groups.Include(g => g.Items)
            .Where(g => affectedGroupIds.Contains(g.Id))
            .ToListAsync(cancellationToken);

        foreach (var group in groups)
        {
            group.RemoveElement(kind, elementId);
            await stats.RecomputeAsync(group, cancellationToken);
        }
    }
}
