using LiteCqrs;
using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;

namespace TeleWave.Application.Library.Collections.GetCollection;

public sealed class GetCollectionQueryHandler(IAppDbContext dbContext)
    : IQueryHandler<GetCollectionQuery, Result<CollectionDto>>
{
    public async Task<Result<CollectionDto>> Handle(
        GetCollectionQuery query,
        CancellationToken cancellationToken
    )
    {
        var collection = await dbContext
            .Collections.AsNoTracking()
            .Include(c => c.Items)
            .FirstOrDefaultAsync(c => c.Id == query.Id, cancellationToken);
        if (collection is null)
            return Result.Failure<CollectionDto>(CollectionErrors.NotFound);

        var showIds = collection.Items.Select(i => i.ShowId).ToList();
        var shows = await dbContext
            .Shows.AsNoTracking()
            .Where(s => showIds.Contains(s.Id))
            .Select(s => new
            {
                s.Id,
                s.Name,
                s.Kind,
                s.Audience,
                s.Year,
                s.PosterImageId,
                EpisodeCount = s.Episodes.Count,
            })
            .ToDictionaryAsync(s => s.Id, cancellationToken);

        var items = collection
            .Items.OrderBy(i => i.Position)
            .Select(i =>
            {
                shows.TryGetValue(i.ShowId, out var show);
                return new CollectionItemDto(
                    i.ShowId,
                    i.Position,
                    show?.Name ?? "—",
                    show?.Kind ?? default,
                    show?.Audience,
                    show?.EpisodeCount ?? 0,
                    show?.Year,
                    show?.PosterImageId
                );
            })
            .ToList();

        return Result.Success(
            new CollectionDto(
                collection.Id,
                collection.Name,
                collection.Description,
                collection.PosterImageId,
                collection.CreatedAt,
                items
            )
        );
    }
}
