using System.Collections.Generic;
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudInfrastructure.Services.DetectOperations;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using Xunit;

namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors;

public class DetectorDrillingTests : DetectorDrilling
{
   private const int idSlide = 5002;
   private const int idRotor = 5003;

   [Theory]
   [MemberData(nameof(TelemetryRangeDrillingRotor))]
   public void DefineDrillingOperation_ShouldReturn_DrillingRotor(DetectableTelemetry[] telemetryRange)
   {
      //act
      var result = GetSpecificInformation(telemetryRange, 0, telemetryRange.Length);

      //assert
      Assert.Equal(idRotor, result.IdCategory);
   }

   [Theory]
   [MemberData(nameof(TelemetryRangeDrillingSlide))]
   public void DefineDrillingOperation_ShouldReturn_DrillingSlide(DetectableTelemetry[] telemetryRange)
   {
      //act
      var result = GetSpecificInformation(telemetryRange, 0, telemetryRange.Length);

      //assert
      Assert.Equal(idSlide, result.IdCategory);
   }

   [Theory]
   [MemberData(nameof(TelemetryRangeDrillingSlideWithOscillation))]
   public void DefineDrillingOperation_ShouldReturn_DrillingSlideWithOscillation(DetectableTelemetry[] telemetryRange)
   {
      //act
      var result = GetSpecificInformation(telemetryRange, 0, telemetryRange.Length);

      //assert
      var oHasOscillation = result.ExtraData[ExtraDataKeyHasOscillation];

      Assert.Equal(idSlide, result.IdCategory);
      Assert.True(oHasOscillation is bool hasOscillation && hasOscillation);
   }

   [Fact]
   public void IsValidOperationDetectorResult_ShouldReturn_True()
   {
      //arrange
      var operationDetectorResult = new OperationDetectorResult
      {
         Operation = new DetectedOperationDto
         {
            DepthStart = 5000,
            DepthEnd = 6000,
            DateStart = System.DateTimeOffset.Now.AddMinutes(-1),
            DateEnd = System.DateTimeOffset.Now,
            }
      };

      //act
      var result = IsValidOperationDetectorResult(operationDetectorResult);
      
      //assert
      Assert.True(result);
   }

   [Fact]
   public void IsValidOperationDetectorResult_ShouldReturn_False()
   {
      //arrange
      var operationDetectorResult = new OperationDetectorResult
      {
         Operation = new DetectedOperationDto
         {
            DepthStart = 5000,
            DepthEnd = 5000,
                DateStart = System.DateTimeOffset.Now.AddMinutes(-1),
                DateEnd = System.DateTimeOffset.Now,
            }
      };

      //act
      var result = IsValidOperationDetectorResult(operationDetectorResult);
      
      //assert
      Assert.False(result);
   }

   public static IEnumerable<object[]> TelemetryRangeDrillingRotor()
   {
      yield return new object[]
      {
         new[]
         {
            new DetectableTelemetry
            {
               WellDepth = 4.187f,
               Pressure = 27.815952f,
               HookWeight = 34.221367f,
               BlockPosition = 24.388f,
               BitDepth = 4.187f,
               RotorSpeed = 40.3f
            },
            new DetectableTelemetry
            {
               WellDepth = 4.232f,
               Pressure = 28.080372f,
               HookWeight = 34.162174f,
               BlockPosition = 24.343f,
               BitDepth = 4.232f,
               RotorSpeed = 40.3f
            },
            new DetectableTelemetry
            {
               WellDepth = 4.277f,
               Pressure = 29.047901f,
               HookWeight = 33.688717f,
               BlockPosition = 24.298f,
               BitDepth = 24.298f,
               RotorSpeed = 40.3f
            },
            new DetectableTelemetry
            {
               WellDepth = 4.309f,
               Pressure = 29.574032f,
               HookWeight = 33.692104f,
               BlockPosition = 24.266f,
               BitDepth = 4.309f,
               RotorSpeed = 40.4f
            },
            new DetectableTelemetry
            {
               WellDepth = 4.324f,
               Pressure = 24.007977f,
               HookWeight = 34.838448f,
               BlockPosition = 24.251f,
               BitDepth = 4.324f,
               RotorSpeed = 40.5f
            },
            new DetectableTelemetry
            {
               WellDepth = 4.324f,
               Pressure = 24.04114f,
               HookWeight = 34.423424f,
               BlockPosition = 24.252f,
               BitDepth = 4.323f,
               RotorSpeed = 40.3f
            }
         }
      };
   }

   public static IEnumerable<object[]> TelemetryRangeDrillingSlide()
   {
      yield return new object[]
      {
         new[]
         {
            new DetectableTelemetry
            {
               WellDepth = 447.276001f,
               Pressure = 26.619421f,
               HookWeight = 40.9143829f,
               BlockPosition = 4.559f,
               BitDepth = 477.265991f,
               RotorSpeed = 0
            },
            new DetectableTelemetry
            {
               WellDepth = 477.289f,
               Pressure = 28.716f,
               HookWeight = 38.27f,
               BlockPosition = 4.5f,
               BitDepth = 477.289f,
               RotorSpeed = 0.1f
            },
            new DetectableTelemetry
            {
               WellDepth = 477.30899f,
               Pressure = 33.953495f,
               HookWeight = 38.27f,
               BlockPosition = 4.5359997f,
               BitDepth = 477.289001f,
               RotorSpeed = 0.1f
            },
         }
      };
   }

   public static IEnumerable<object[]> TelemetryRangeDrillingSlideWithOscillation()
   {
      yield return new object[]
      {
         new[]
         {
            new DetectableTelemetry
            {
               WellDepth = 415.306f,
               Pressure = 53.731934f,
               HookWeight = 41.049942f,
               BlockPosition = 28.666f,
               BitDepth = 415.293f,
               RotorSpeed = 0.3f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.311f,
               Pressure = 57.660595f,
               HookWeight = 40.898712f,
               BlockPosition = 28.648f,
               BitDepth = 415.311f,
               RotorSpeed = 0.2f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.326f,
               Pressure = 59.211086f,
               HookWeight = 40.882797f,
               BlockPosition = 28.633f,
               BitDepth = 415.326f,
               RotorSpeed = 0.1f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.344f,
               Pressure = 59.484406f,
               HookWeight = 40.91972f,
               BlockPosition = 28.615f,
               BitDepth = 415.344f,
               RotorSpeed = 0.2f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.364f,
               Pressure = 60.739918f,
               HookWeight = 40.795666f,
               BlockPosition = 28.595f,
               BitDepth = 415.364f,
               RotorSpeed = 4.5f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.378f,
               Pressure = 62.528984f,
               HookWeight = 40.52114f,
               BlockPosition = 28.581f,
               BitDepth = 415.378f,
               RotorSpeed = 22.6f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.392f,
               Pressure = 67.0039f,
               HookWeight = 38.878895f,
               BlockPosition = 28.569f,
               BitDepth = 415.39f,
               RotorSpeed = 50f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.392f,
               Pressure = 65.72418f,
               HookWeight = 42.53173f,
               BlockPosition = 28.622f,
               BitDepth = 415.337f,
               RotorSpeed = 93f
            },
            new DetectableTelemetry
            {
               WellDepth = 415.392f,
               Pressure = 56.82195f,
               HookWeight = 43.15844f,
               BlockPosition = 28.704f,
               BitDepth = 415.255f,
               RotorSpeed = 71.5f
            }
         }
      };
   }
}