using CSharpFunctionalExtensions;
using System;
using System.Collections.Generic;

namespace LaValidation
{
   public class Session : ValueObject
   {
       readonly DateRange range;
       readonly Maybe<Place> place;
       private Session(DateRange range, Maybe<Place> place)
       {
           this.range = range;
           this.place = place;
       }

   public static Result<Session, Error> Create(DateRange range,   
   Maybe<Place> place)
      {
       if (place.HasValue && (range.NumberOfDay() > 5 || 
       range.Contains(DayOfWeek.Sunday)))
       return Result.Failure<Session, 
       Error>(Errors.Session.PresentialMustLastAWeekMax());
       return new Session(range, place);
      }

   protected override IEnumerable<object> GetEqualityComponents()
       {
           yield return this.range;
           yield return this.place;
       }
   }
}

using FluentValidation;
namespace LaValidation
{
   public class SessionValidator : AbstractValidator<SessionDto>
   {
       public SessionValidator()
       {
         RuleFor(s => s.Begin).NotEmpty().WithMessage("Begin date 
           must have a value");
         RuleFor(s => s.End).NotEmpty().WithMessage("End date must  
           have a value");
         RuleFor(s => s).MustBeValueObject(s => Session.Create(new 
            DateRange(s.Begin, s.End), Place.Create(s.InseeCode)));
       }
   }
}

using System;
namespace LaValidation
{
   public class SessionDto
   {
       public DateTime Begin { get; set; }
       public DateTime End { get; set; }
       public string InseeCode { get; set; }
   }
}

using System;
using Xunit;
using FluentAssertions;
namespace LaValidation.Tests
{
   public class SessionValidatorTest
   {
       /// <summary>
       /// SessionDto validation example
       /// </summary>
   [Fact]
   public void a_presential_session_longer_than_one_week_shoudld_be_invalid_dto()
      {
         //given
         var invalidPresentialSession = new SessionDto()
         { InseeCode = "75001", Begin = new DateTime(2021,1,1), End  
         = new DateTime(2021, 1, 8) };
         
        // when
        var validationResult =  new SessionValidator().Validate(invalidPresentialSession);

        // then
        validationResult.Errors.Should().ContainSingle(a => a.ErrorMessage == "session.invalid.date||A presential session should last one week maximum and cannot contain sunday");
       }

       /// <summary>
       /// Session Domain model validation example
       /// </summary>
       [Fact]
       public void a_presential_session_longer_than_one_week_shoudld_be_invalid_core_domain()
       {
          //given
      var longerThanAWeek = new DateRange(new DateTime(2021, 1, 1),  
        new DateTime(2021, 1, 8));
      var paris = Place.Create("75001");

           // when
       var validationResult = Session.Create(longerThanAWeek,paris);

           // then
           validationResult.Error.Should().Be(Errors.Session.PresentialMustLastAWeekMax());
       }
   }
}