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

namespace TeleWave.Application.Programming.Groups;

/// <summary>
/// Пересчёт кэша статистики группы. Вызывается при каждой правке состава: цифры «342 позиции ·
/// 118 ч» видны прямо в инспекторе слота, и устаревшая статистика там хуже, чем её отсутствие.
/// </summary>
public sealed class GroupStatsService(
    IAppDbContext dbContext,
    GroupElementResolver resolver,
    DynamicGroupResolver dynamicResolver
)
{
    public async Task RecomputeAsync(Group group, CancellationToken cancellationToken)
    {
        // Считаем по вычисленному составу, а не по списку позиций: у динамической группы список —
        // это только поправки, и «342 позиции» из него получились бы неправдой.
        var composition = await dynamicResolver.ResolveAsync(group, cancellationToken);
        var info = await resolver.ResolveAsync(
            composition.Select(e => (e.Kind, e.Id)),
            cancellationToken
        );

        var unitCount = 0;
        var totalDuration = TimeSpan.Zero;
        foreach (var element in composition)
        {
            if (!info.TryGetValue((element.Kind, element.Id), out var resolved))
                continue;
            unitCount += resolved.UnitCount;
            totalDuration += resolved.TotalDuration;
        }

        group.UpdateStats(composition.Count, unitCount, totalDuration, DateTimeOffset.UtcNow);
    }

    /// <summary>Пересчитать по идентификатору, загрузив состав. Возвращает false, если группы нет.</summary>
    public async Task<bool> RecomputeAsync(Guid groupId, CancellationToken cancellationToken)
    {
        var group = await dbContext
            .Groups.Include(g => g.Items)
            .FirstOrDefaultAsync(g => g.Id == groupId, cancellationToken);
        if (group is null)
            return false;

        await RecomputeAsync(group, cancellationToken);
        return true;
    }
}
