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
				}
			}
		};
	}
}