using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.ProgramSchedules; public class CreateProgramScheduleHandler : IRequestHandler> { private readonly IDbContextFactory _dbContextFactory; public CreateProgramScheduleHandler(IDbContextFactory dbContextFactory) => _dbContextFactory = dbContextFactory; public async Task> Handle( CreateProgramSchedule request, CancellationToken cancellationToken) { await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken); Validation validation = await Validate(dbContext, request); return await validation.Apply(ps => PersistProgramSchedule(dbContext, ps)); } private static async Task PersistProgramSchedule( TvContext dbContext, ProgramSchedule programSchedule) { await dbContext.ProgramSchedules.AddAsync(programSchedule); await dbContext.SaveChangesAsync(); return new CreateProgramScheduleResult(programSchedule.Id); } private static Task> Validate( TvContext dbContext, CreateProgramSchedule request) => ValidateName(dbContext, request).MapT( name => { bool keepMultiPartEpisodesTogether = request.KeepMultiPartEpisodesTogether; return new ProgramSchedule { Name = name, KeepMultiPartEpisodesTogether = keepMultiPartEpisodesTogether, TreatCollectionsAsShows = keepMultiPartEpisodesTogether && request.TreatCollectionsAsShows, ShuffleScheduleItems = request.ShuffleScheduleItems, RandomStartPoint = request.RandomStartPoint }; }); private static async Task> ValidateName( TvContext dbContext, CreateProgramSchedule createProgramSchedule) { Validation result1 = createProgramSchedule.NotEmpty(c => c.Name) .Bind(_ => createProgramSchedule.NotLongerThan(50)(c => c.Name)); int duplicateNameCount = await dbContext.ProgramSchedules .CountAsync(ps => ps.Name == createProgramSchedule.Name); var result2 = Optional(duplicateNameCount) .Where(count => count == 0) .ToValidation("Schedule name must be unique"); return (result1, result2).Apply((_, _) => createProgramSchedule.Name); } }