using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DetectOperations;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using Xunit;

namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors;

/// <summary>
/// Тестирование автоопределения операции "Промывка"
/// </summary>
public class DetectorFlashingTests : DetectorFlashing
{
    private readonly DetectorFlashing detector = new();

    /// <summary>
    /// Операция, попадающая под автоопределение операции промывки
    /// </summary>
    private readonly DetectableTelemetry telemetry = new()
    {
        Pressure = 21,
        WellDepth = 152,
        BitDepth = 151,
        RotorSpeed = 9,
        DateTime = System.DateTimeOffset.Now
    };


    /// <summary>
    /// Тестирование операций, попадающей под автоопределение операции промывки, при этом
    /// - найден признак начала операции
    /// - не найден признак окончания операции
    /// </summary>
    [Fact]
    public void DetectOperation_find_startOperation_notFind_endOperation()
    {
        //arrange
        var point0 = telemetry.Copy();
        var point1 = telemetry.Copy();
        point1.DateTime = System.DateTimeOffset.Now.AddMinutes(5);

        var telemetries = new[] { point0, point1 };

        //act
        var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);

        //assert
        Assert.True(isDetectOperation);
        Assert.NotNull(result);
        Assert.Equal(WellOperationCategory.IdFlashing, result.Operation.IdCategory);
        Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]);
    }

    /// <summary>
    /// Операция, у которой глубина долота = 150м, не является промывкой 
    /// </summary>
    [Fact]
    public void DetectOperation_with_BitDepth_LE_150_is_fail()
    {
        //arrange
        var point0 = telemetry.Copy();
        point0.BitDepth = 150;

        var point1 = telemetry.Copy();

        var telemetries = new[] { point0, point1 };

        //act

        var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);

        //assert
        Assert.False(isDetectOperation);
        Assert.Null(result);
    }


    /// <summary>
    /// Операция, у которой меняется глубина забоя, не является промывкой 
    /// </summary>
    [Fact]
    public void DetectOperation_with_DeltaWellDepth_NotEqual_0_is_fail()
    {
        //arrange
        var point0 = telemetry.Copy();
        var point1 = telemetry.Copy();
        point1.WellDepth = point0.WellDepth + 10;

        var telemetries = new[] { point0, point1 };

        //act
        var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);

        //assert
        Assert.False(isDetectOperation);
        Assert.Null(result);
    }

    /// <summary>
    /// Найдены начальная и конечная операции промывки,
    /// Признак окончания операции - снижение давления менее 10 атм
    /// </summary>
    [Fact]
    public void DetectOperations_Begin_And_End_by_Pressure_Less_20_is_success()
    {
        //arrange
        var point0 = telemetry.Copy();
        var point1 = telemetry.Copy();
        point1.Pressure = 9;
        point1.BitDepth = 140.0001f;
        point1.RotorSpeed = 10;

        var telemetries = new[] { point0, point1 };

        //act
        var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);

        //assert
        Assert.False(isDetectOperation);
        Assert.NotNull(result);
        Assert.Equal(WellOperationCategory.IdFlashing, result.Operation.IdCategory);
        Assert.Equal(IdReasonOfEnd_PressureIsLo, result.Operation.ExtraData["IdReasonOfEnd"]);
    }


}