using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Core.Observability;

namespace ZB.MOM.WW.OtOpcUa.Core.Tests.Observability;

[Trait("Category", "Unit")]
public sealed class DriverHealthReportTests
{
    [Fact]
    public void EmptyFleet_IsHealthy()
    {
        DriverHealthReport.Aggregate([]).ShouldBe(ReadinessVerdict.Healthy);
    }

    [Fact]
    public void AllHealthy_Fleet_IsHealthy()
    {
        var verdict = DriverHealthReport.Aggregate([
            new DriverHealthSnapshot("a", DriverState.Healthy),
            new DriverHealthSnapshot("b", DriverState.Healthy),
        ]);
        verdict.ShouldBe(ReadinessVerdict.Healthy);
    }

    [Fact]
    public void AnyFaulted_TrumpsEverything()
    {
        var verdict = DriverHealthReport.Aggregate([
            new DriverHealthSnapshot("a", DriverState.Healthy),
            new DriverHealthSnapshot("b", DriverState.Degraded),
            new DriverHealthSnapshot("c", DriverState.Faulted),
            new DriverHealthSnapshot("d", DriverState.Initializing),
        ]);
        verdict.ShouldBe(ReadinessVerdict.Faulted);
    }

    [Theory]
    [InlineData(DriverState.Unknown)]
    [InlineData(DriverState.Initializing)]
    public void Any_NotReady_WithoutFaulted_IsNotReady(DriverState initializingState)
    {
        var verdict = DriverHealthReport.Aggregate([
            new DriverHealthSnapshot("a", DriverState.Healthy),
            new DriverHealthSnapshot("b", initializingState),
        ]);
        verdict.ShouldBe(ReadinessVerdict.NotReady);
    }

    [Fact]
    public void Any_Degraded_WithoutFaultedOrNotReady_IsDegraded()
    {
        var verdict = DriverHealthReport.Aggregate([
            new DriverHealthSnapshot("a", DriverState.Healthy),
            new DriverHealthSnapshot("b", DriverState.Degraded),
        ]);
        verdict.ShouldBe(ReadinessVerdict.Degraded);
    }

    [Theory]
    [InlineData(ReadinessVerdict.Healthy, 200)]
    [InlineData(ReadinessVerdict.Degraded, 200)]
    [InlineData(ReadinessVerdict.NotReady, 503)]
    [InlineData(ReadinessVerdict.Faulted, 503)]
    public void HttpStatus_MatchesStateMatrix(ReadinessVerdict verdict, int expected)
    {
        DriverHealthReport.HttpStatus(verdict).ShouldBe(expected);
    }
}
