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

namespace TeleWave.Application.Library.Collections.Suggest;

public sealed class CreateCollectionFromSuggestionCommandHandler(
    IAppDbContext dbContext,
    CollectionSuggestionBuilder builder,
    CollectionPosterPicker posters
) : ICommandHandler<CreateCollectionFromSuggestionCommand, Result<Guid>>
{
    public async Task<Result<Guid>> Handle(
        CreateCollectionFromSuggestionCommand command,
        CancellationToken cancellationToken
    )
    {
        var suggestions = await builder.BuildAsync(cancellationToken);
        var suggestion = suggestions.FirstOrDefault(s => s.Key == command.Key);
        if (suggestion is null)
            return Result.Failure<Guid>(CollectionErrors.SuggestionNotFound);

        // Сравниваем имена в памяти, а не запросом: коллекций десятки, зато проверка идёт по тем же
        // правилам, что и пометка «уже есть» в списке предложений. SQL-регистронезависимость
        // (lower()) в тонких местах вроде «ё» с ней расходится, и предложение то показывалось бы
        // доступным, то отбивалось конфликтом.
        var names = await dbContext.Collections.Select(c => c.Name).ToListAsync(cancellationToken);
        if (
            names.Any(name =>
                string.Equals(
                    name.Trim(),
                    suggestion.Name,
                    StringComparison.CurrentCultureIgnoreCase
                )
            )
        )
            return Result.Failure<Guid>(CollectionErrors.SuggestionAlreadyCreated);

        var collection = Collection.Create(suggestion.Name);
        foreach (var part in suggestion.Parts)
            collection.AddShow(part.ShowId);

        dbContext.Collections.Add(collection);

        // Постер берём у первой части: франшиза узнаётся по обложке первого фильма, а коллекция
        // без картинки теряется в списке среди таких же безымянных прямоугольников.
        await posters.FillAsync([collection], cancellationToken);

        return Result.Success(collection.Id);
    }
}
