// using AsbCloudApp.Data;
// using AsbCloudDb.Model;
// using AsbCloudInfrastructure;
// using AsbCloudWebApi.IntegrationTests.Clients;
// using Mapster;
// using Microsoft.EntityFrameworkCore;
// using Microsoft.EntityFrameworkCore.ChangeTracking;
// using System.Net;
// using Xunit;
//
// namespace AsbCloudWebApi.IntegrationTests.Controllers
// {
//     public abstract class CrudWellRelatedClient<TDto, TEntity> : BaseIntegrationTest
//         where TDto : AsbCloudApp.Data.IId, AsbCloudApp.Data.IWellRelated
//         where TEntity : class, AsbCloudDb.Model.IId, AsbCloudDb.Model.IWellRelated
//     {
//         public abstract IEnumerable<TDto> ValidDtos { get; }
//         public abstract IEnumerable<TDto> InvalidDtos { get; }
//         public abstract IEnumerable<TDto> ForbiddenDtos { get; }
//         protected List<string> ExcludeProps { get; set; } = new() { "Id" };
//
//         protected ICrudWellRelatedClient<TDto> client;        
//
//         public CrudWellRelatedClient(WebAppFactoryFixture factory, string uriSuffix) 
//             : base(factory)
//         {
//             client = factory.GetAuthorizedHttpClient<ICrudWellRelatedClient<TDto>>(uriSuffix);
//         }
//
//         protected async Task<DbSet<TEntity>> GetCleanDbSet()
//         {
//             var dbset = dbContext.Set<TEntity>();
//             dbset.RemoveRange(dbset);
//             await dbContext.SaveChangesAsync(CancellationToken.None);
//             return dbset;
//         }
//
//         [Fact]
//         public async Task Insert_returns_success_for_validDtos()
//         {
//             foreach (var validDto in ValidDtos)
//                 await Insert_returns_success(validDto);
//         }
//
//         private async Task Insert_returns_success(TDto validDto)
//         {
//             var dbset = await GetCleanDbSet();
//
//             //act
//             var response = await client.InsertAsync(validDto);
//
//             //assert
//             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
//             Assert.True(response.Content > 0);
//
//             var entity = dbset.First();
//             var fromDbDto = Convert(entity);
//             MatchHelper.Match(validDto, fromDbDto, ExcludeProps);
//         }
//
//         [Fact]
//         public async Task Insert_returns_badRequest_for_invalidDtos()
//         {
//             foreach (var inValidDto in InvalidDtos)
//                 await Insert_returns_badRequest(inValidDto);
//         }
//
//         private async Task Insert_returns_badRequest(TDto invalidDto)
//         {
//             await GetCleanDbSet();
//
//             //act
//             var response = await client.InsertAsync(invalidDto);
//
//             //assert
//             Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
//         }
//
//         [Fact]
//         public async Task Insert_returns_forbidden_for_forbiddenDtos()
//         {
//             foreach (var forbiddenDto in ForbiddenDtos)
//                 await Insert_returns_forbidden(forbiddenDto);
//         }
//
//         private async Task Insert_returns_forbidden(TDto forbiddenDto)
//         {
//             await GetCleanDbSet();
//
//             //act
//             var response = await client.InsertAsync(forbiddenDto);
//
//             //assert
//             Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
//         }
//
//         [Fact]
//         public async Task GetAllAsync_returns_data()
//         {
//             //arrange
//             var dbset = await GetCleanDbSet();
//             var entries = new List<(EntityEntry<TEntity>, TDto)>();
//
//             foreach (var dto in ValidDtos)
//             {
//                 var entity = Convert(dto);
//                 entity.Id = 0;
//                 var entry = dbset.Add(entity);                
//                 entries.Add((entry, dto));
//             }
//             dbContext.SaveChanges();
//             
//             //act
//             var response = await client.GetAllAsync();
//
//             //assert
//             Assert.Equal(HttpStatusCode.OK, response.StatusCode);
//             Assert.NotNull(response.Content);
//             Assert.Equal(entries.Count, response.Content.Count());
//
//             foreach (var item in response.Content)
//             {
//                 var entry = entries.First(e => e.Item1.Entity.Id == item.Id);
//                 MatchHelper.Match(entry.Item2, item, ExcludeProps);
//             }
//         }
//
//         protected virtual TDto Convert(TEntity entity)
//         {
//             var dto = entity.Adapt<TDto>();
//             return dto;
//         }
//
//         protected virtual TEntity Convert(TDto dto)
//         {
//             var entity = dto.Adapt<TEntity>();
//             return entity;
//         }
//     }
//
//     public class ScheduleControllerTest : CrudWellRelatedClient<ScheduleDto, Schedule>
//     {
//         static Driller driller = Data.Defaults.Drillers.First();
//         static DrillerDto drillerDto = driller.Adapt<DrillerDto>();
//
//         static Well well = Data.Defaults.Wells.First();
//
//         public override IEnumerable<ScheduleDto> ValidDtos { get; } = new ScheduleDto[]
//         {
//             new() {
//                 Id = 1,
//                 IdWell = well.Id,
//                 Driller = drillerDto,
//                 IdDriller = driller.Id,
//                 DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified),
//                 DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified),
//                 ShiftStart = new TimeDto(8, 0, 0),
//                 ShiftEnd = new TimeDto(20, 0, 0),
//             },
//             new() {
//                 Id = 1,
//                 IdWell = well.Id,
//                 Driller = drillerDto,
//                 IdDriller = driller.Id,
//                 DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified),
//                 DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified),
//                 ShiftStart = new TimeDto(20, 0, 0),
//                 ShiftEnd = new TimeDto(8, 0, 0),
//             }
//         };
//
//         public override IEnumerable<ScheduleDto> InvalidDtos { get; } = new ScheduleDto[]
//         {
//             new() {
//                 IdWell = well.Id,
//                 Driller = drillerDto,
//                 IdDriller = driller.Id,
//                 DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified),
//                 DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified),
//                 ShiftStart = new TimeDto(8, 0, 0),
//                 ShiftEnd = new TimeDto(20, 0, 0),
//             },
//             new() {
//                 IdWell = well.Id,
//                 Driller = drillerDto,
//                 IdDriller = int.MaxValue - 1,
//                 DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified),
//                 DrillEnd = new DateTime(2024, 1, 2, 0, 0, 0, DateTimeKind.Unspecified),
//                 ShiftStart = new TimeDto(8, 0, 0),
//                 ShiftEnd = new TimeDto(20, 0, 0),
//             }
//         };
//
//         public override IEnumerable<ScheduleDto> ForbiddenDtos { get; } = new ScheduleDto[] {
//             new() {
//                 IdWell = int.MaxValue - 1,
//                 Driller = drillerDto,
//                 IdDriller = driller.Id,
//                 DrillStart = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Unspecified),
//                 DrillEnd = new DateTime(2022, 1, 2, 0, 0, 0, DateTimeKind.Unspecified),
//                 ShiftStart = new TimeDto(8, 0, 0),
//                 ShiftEnd = new TimeDto(20, 0, 0),
//             }
//         };
//
//         public ScheduleControllerTest(WebAppFactoryFixture factory) 
//             : base(factory, "api/schedule")
//         {
//             ExcludeProps.Add(nameof(ScheduleDto.Driller));
//         }
//
//         protected override ScheduleDto Convert(Schedule entity)
//         {
//             var dto = base.Convert(entity);
//             dto.DrillStart = entity.DrillStart.ToRemoteDateTime(well.Timezone.Hours);
//             dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(well.Timezone.Hours);
//             return dto;
//         }
//
//         protected override Schedule Convert(ScheduleDto dto)
//         {
//             var entity = base.Convert(dto);
//             entity.DrillStart = dto.DrillStart.FromTimeZoneOffsetHours(well.Timezone.Hours);
//             entity.DrillEnd = dto.DrillEnd.FromTimeZoneOffsetHours(well.Timezone.Hours);
//             return entity;
//         }
//     }
// }