using JSMR.Application.Circles.Queries.GetTags;
using Microsoft.EntityFrameworkCore;

namespace JSMR.Infrastructure.Data.Repositories.Circles;

public class CircleTagsProvider(AppDbContext context) : ICircleTagsProvider
{
    public async Task<GetCircleTagsResponse> HandleAsync(GetCircleTagsRequest request, CancellationToken cancellationToken = default)
    {
        int? circleId = await CircleLookup.ResolveCircleIdAsync(context, request.CircleId, request.NameOrMakerId, cancellationToken);

        if (circleId is null)
            return new GetCircleTagsResponse([]);

        IQueryable<CircleTagItem> query =
            from voiceWork in context.VoiceWorks.AsNoTracking()
            where voiceWork.CircleId == circleId.Value
            join voiceWorkTag in context.VoiceWorkTags.AsNoTracking() on voiceWork.VoiceWorkId equals voiceWorkTag.VoiceWorkId
            join tag in context.Tags.AsNoTracking() on voiceWorkTag.TagId equals tag.TagId
            join englishTag in context.EnglishTags.AsNoTracking() on tag.TagId equals englishTag.TagId into eng
            from e in eng.DefaultIfEmpty()
            group new { tag, e } by new { tag.Name, English = e != null ? e.Name : null } into g
            orderby g.Count() descending
            select new CircleTagItem(
                g.Key.Name,
                g.Key.English,
                g.Count());

        CircleTagItem[] items = await query.ToArrayAsync(cancellationToken);

        return new GetCircleTagsResponse(items);
    }
}