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

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

/// <summary>
///     Covers <see cref="DriverHealth"/> shape invariants — added to lock down the documented
///     contract after Core.Abstractions-008 reworded the <c>LastError</c> remark.
/// </summary>
public sealed class DriverHealthTests
{
    /// <summary>
    ///     Core.Abstractions-008: <c>DriverHealth.LastError</c> is not constrained by the
    ///     <c>State</c> enum — a Healthy driver may legitimately retain the last error from a
    ///     recovered failure (for diagnostics), and Degraded / Reconnecting / Faulted states may
    ///     all carry a non-null message. The old XML doc "null when state is Healthy" was wrong;
    ///     this test makes the type's actual contract explicit so future doc churn cannot drift.
    /// </summary>
    /// <param name="state">The driver state to test.</param>
    [Theory]
    [InlineData(DriverState.Unknown)]
    [InlineData(DriverState.Initializing)]
    [InlineData(DriverState.Healthy)]
    [InlineData(DriverState.Degraded)]
    [InlineData(DriverState.Reconnecting)]
    [InlineData(DriverState.Faulted)]
    public void LastError_IsIndependent_OfState(DriverState state)
    {
        var healthWithError = new DriverHealth(state, LastSuccessfulRead: DateTime.UtcNow, LastError: "earlier failure");
        var healthWithoutError = new DriverHealth(state, LastSuccessfulRead: DateTime.UtcNow, LastError: null);

        // Both shapes are constructible regardless of state — the type makes no enforcement.
        healthWithError.LastError.ShouldBe("earlier failure");
        healthWithoutError.LastError.ShouldBeNull();
        healthWithError.State.ShouldBe(state);
        healthWithoutError.State.ShouldBe(state);
    }

    /// <summary>Verifies that DriverState enum contains all expected members.</summary>
    [Fact]
    public void DriverState_EnumContainsExpectedMembers()
    {
        // Pins the enum so finding-008's "more than Healthy can carry an error" claim
        // does not bit-rot.
        var names = Enum.GetNames<DriverState>();
        names.ShouldContain(nameof(DriverState.Unknown));
        names.ShouldContain(nameof(DriverState.Initializing));
        names.ShouldContain(nameof(DriverState.Healthy));
        names.ShouldContain(nameof(DriverState.Degraded));
        names.ShouldContain(nameof(DriverState.Reconnecting));
        names.ShouldContain(nameof(DriverState.Faulted));
    }
}
