using AsbCloudApp.Data;
using AsbCloudApp.Requests;
using AsbCloudDb.Model;
using AsbCloudWebApi.IntegrationTests.Clients;
using Xunit;

namespace AsbCloudWebApi.IntegrationTests.Controllers;

public class SlipsStatControllerTest : BaseIntegrationTest
{
   private readonly ISlipsTimeClient client;

   public SlipsStatControllerTest(WebAppFactoryFixture factory)
      : base(factory)
   {
      client = factory.GetAuthorizedHttpClient<ISlipsTimeClient>(string.Empty);

      dbContext.CleanupDbSet<Schedule>();
      dbContext.CleanupDbSet<WellOperation>();
      dbContext.CleanupDbSet<DetectedOperation>();
   }

   [Fact]
   public async Task GetAll_returns_success()
   {
      //arrange
      var well = dbContext.Wells.First();
      var schedule = CreateScheduleAsync(well.Id);
      var factWellOperation = CreateFactWellOperation(well.Id);
      var detectedOperation = CreateDetectedOperation(well.IdTelemetry!.Value);

      dbContext.Schedule.Add(schedule);
      dbContext.WellOperations.Add(factWellOperation);
      dbContext.DetectedOperations.Add(detectedOperation);
      await dbContext.SaveChangesAsync();

      var request = new OperationStatRequest
      {
         DateStartUTC = schedule.DrillStart.DateTime,
         DateEndUTC = schedule.DrillEnd.DateTime,
         DurationMinutesMin = 0,
         DurationMinutesMax = 5
      };

      var dtoExpected = new SlipsStatDto
      {
         DrillerName = $"{schedule.Driller.Surname} {schedule.Driller.Name} {schedule.Driller.Patronymic}",
         WellCount = 1,
         SectionCaption = "Пилотный ствол",
         SlipsCount = 1,
         SlipsTimeInMinutes = (detectedOperation.DateEnd - detectedOperation.DateStart).TotalMinutes,
         SectionDepth = factWellOperation.DepthEnd - factWellOperation.DepthStart,
      };

      //act
      var response = await client.GetAll(request);

      //assert
      Assert.NotNull(response.Content);
      Assert.Single(response.Content);

      var slipsStat = response.Content.First();
      MatchHelper.Match(dtoExpected, slipsStat);
   }

   private static Schedule CreateScheduleAsync(int idWell) => new()
   {
      IdWell = idWell,
      ShiftStart = new TimeOnly(8, 0, 0),
      ShiftEnd = new TimeOnly(20, 0, 0),
      DrillStart = new DateTimeOffset(new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
      DrillEnd = new DateTimeOffset(new DateTime(2024, 2, 1, 0, 0, 0, DateTimeKind.Utc)),
      Driller = new Driller
      {
         Name = "TestName",
         Surname = "TestSurname",
         Patronymic = "TestPatronymic"
      }
   };

   private static WellOperation CreateFactWellOperation(int idWell) =>
      new()
      {
         IdWell = idWell,
         IdWellSectionType = 1,
         IdCategory = WellOperationCategory.IdRotor,
         IdType = WellOperation.IdOperationTypeFact,
         DepthStart = 0,
         DepthEnd = 100,
         LastUpdateDate = DateTimeOffset.UtcNow,
         DateStart = new DateTimeOffset(new DateTime(2024, 1, 15, 15, 0, 0, DateTimeKind.Utc)),
         DurationHours = 1
      };

   private static DetectedOperation CreateDetectedOperation(int idTelemetry) =>
      new()
      {
         IdTelemetry = idTelemetry,
         IdCategory = WellOperationCategory.IdSlipsTime,
         DateStart = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 0, 0, 0, DateTimeKind.Utc)),
         DateEnd = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 2, 0, 0, DateTimeKind.Utc)),
         ExtraData = new Dictionary<string, object>
         {
            { "test", 5 }
         }
      };
}