using System.Threading; using System.Threading.Tasks; using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Infrastructure.Data; using LanguageExt; using MediatR; using Microsoft.EntityFrameworkCore; using static LanguageExt.Prelude; using ValidationT_AsyncSync_Extensions = LanguageExt.ValidationT_AsyncSync_Extensions; namespace ErsatzTV.Application.ProgramSchedules.Commands { 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 = _dbContextFactory.CreateDbContext(); 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) => ValidationT_AsyncSync_Extensions.MapT( ValidateName(dbContext, request), name => { bool keepMultiPartEpisodesTogether = request.KeepMultiPartEpisodesTogether; return new ProgramSchedule { Name = name, KeepMultiPartEpisodesTogether = keepMultiPartEpisodesTogether, TreatCollectionsAsShows = keepMultiPartEpisodesTogether && request.TreatCollectionsAsShows }; }); 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); } } }