using Dapper; using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Search; using ErsatzTV.Infrastructure.Data; using ErsatzTV.Infrastructure.Extensions; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.Libraries; public class DeleteLocalLibraryHandler : LocalLibraryHandlerBase, IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; private readonly ISearchIndex _searchIndex; public DeleteLocalLibraryHandler(IDbContextFactory dbContextFactory, ISearchIndex searchIndex) { _dbContextFactory = dbContextFactory; _searchIndex = searchIndex; } public async Task> Handle( DeleteLocalLibrary request, CancellationToken cancellationToken) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await LocalLibraryMustExist(dbContext, request); return await validation.Apply(localLibrary => DoDeletion(dbContext, localLibrary)); } private async Task DoDeletion(TvContext dbContext, LocalLibrary localLibrary) { List ids = await dbContext.Connection.QueryAsync( """ SELECT MediaItem.Id FROM MediaItem INNER JOIN LibraryPath LP on MediaItem.LibraryPathId = LP.Id WHERE LP.LibraryId = @LibraryId """, new { LibraryId = localLibrary.Id }) .Map(result => result.ToList()); await _searchIndex.RemoveItems(ids); _searchIndex.Commit(); await dbContext.Connection.ExecuteAsync( """ DELETE FROM MediaItem WHERE Id IN ( SELECT Id FROM ( SELECT MI.Id FROM MediaItem MI INNER JOIN LibraryPath LP ON MI.LibraryPathId = LP.Id WHERE LP.LibraryId = @LibraryId ) AS MI ) """, new { LibraryId = localLibrary.Id }); // delete all library folders (children first) IOrderedQueryable orderedFolders = dbContext.LibraryFolders .Filter(lf => lf.LibraryPath.LibraryId == localLibrary.Id) .OrderByDescending(lp => lp.Path.Length); foreach (LibraryFolder folder in orderedFolders) { await dbContext.Connection.ExecuteAsync( "DELETE FROM LibraryFolder WHERE Id = @LibraryFolderId", new { LibraryFolderId = folder.Id }); } dbContext.LocalLibraries.Remove(localLibrary); await dbContext.SaveChangesAsync(); return Unit.Default; } private static Task> LocalLibraryMustExist( TvContext dbContext, DeleteLocalLibrary request) => dbContext.LocalLibraries .SelectOneAsync(ll => ll.Id, ll => ll.Id == request.LocalLibraryId) .Map(o => o.ToValidation($"Local library {request.LocalLibraryId} does not exist.")); }