using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.MediaCollections; public class AddItemsToPlaylistHandler : IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; private readonly IMovieRepository _movieRepository; private readonly ITelevisionRepository _televisionRepository; public AddItemsToPlaylistHandler( IDbContextFactory dbContextFactory, IMovieRepository movieRepository, ITelevisionRepository televisionRepository) { _dbContextFactory = dbContextFactory; _movieRepository = movieRepository; _televisionRepository = televisionRepository; } public async Task> Handle(AddItemsToPlaylist request, CancellationToken cancellationToken) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); return await validation.Apply(c => ApplyAddItemsRequest(dbContext, c, request)); } private static async Task ApplyAddItemsRequest( TvContext dbContext, Playlist playlist, AddItemsToPlaylist request) { var allItems = new Dictionary> { { ProgramScheduleItemCollectionType.Movie, request.MovieIds }, { ProgramScheduleItemCollectionType.TelevisionShow, request.ShowIds }, { ProgramScheduleItemCollectionType.TelevisionSeason, request.SeasonIds }, { ProgramScheduleItemCollectionType.Episode, request.EpisodeIds }, { ProgramScheduleItemCollectionType.Artist, request.ArtistIds }, { ProgramScheduleItemCollectionType.MusicVideo, request.MusicVideoIds }, { ProgramScheduleItemCollectionType.OtherVideo, request.OtherVideoIds }, { ProgramScheduleItemCollectionType.Song, request.SongIds }, { ProgramScheduleItemCollectionType.Image, request.ImageIds } }; int index = playlist.Items.Count > 0 ? playlist.Items.Max(i => i.Index) + 1 : 0; foreach ((ProgramScheduleItemCollectionType collectionType, List ids) in allItems) { foreach (int id in ids) { var item = new PlaylistItem { Index = index++, CollectionType = collectionType, MediaItemId = id, PlaybackOrder = PlaybackOrder.Shuffle, IncludeInProgramGuide = true }; playlist.Items.Add(item); } } await dbContext.SaveChangesAsync(); return Unit.Default; } private async Task> Validate( TvContext dbContext, AddItemsToPlaylist request) => (await PlaylistMustExist(dbContext, request), await ValidateMovies(request), await ValidateShows(request), await ValidateSeasons(request), await ValidateEpisodes(request)) .Apply((collection, _, _, _, _) => collection); private static Task> PlaylistMustExist( TvContext dbContext, AddItemsToPlaylist request) => dbContext.Playlists .Include(c => c.Items) .SelectOneAsync(c => c.Id, c => c.Id == request.PlaylistId) .Map(o => o.ToValidation("Playlist does not exist.")); private Task> ValidateMovies(AddItemsToPlaylist request) => _movieRepository.AllMoviesExist(request.MovieIds) .Map(Optional) .Filter(v => v == true) .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Movie does not exist")); private Task> ValidateShows(AddItemsToPlaylist request) => _televisionRepository.AllShowsExist(request.ShowIds) .Map(Optional) .Filter(v => v == true) .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Show does not exist")); private Task> ValidateSeasons(AddItemsToPlaylist request) => _televisionRepository.AllSeasonsExist(request.SeasonIds) .Map(Optional) .Filter(v => v == true) .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Season does not exist")); private Task> ValidateEpisodes(AddItemsToPlaylist request) => _televisionRepository.AllEpisodesExist(request.EpisodeIds) .Map(Optional) .Filter(v => v == true) .MapT(_ => Unit.Default) .Map(v => v.ToValidation("Episode does not exist")); }