// Go reference: server/monitor.go ClosedState.String() — reason strings emitted by
// the /connz endpoint, and server/auth.go getAuthErrClosedState — auth-related reasons.
// These tests verify the ClosedReason enum and ClosedReasonHelper helpers introduced
// in Task 89 (Gap 10.7: consistently populate closed connection reasons).

using NATS.Server.Monitoring;

namespace NATS.Server.Monitoring.Tests.Monitoring;

public class ClosedReasonTests
{
    // -----------------------------------------------------------------------
    // 1. ToReasonString_ClientClosed_ReturnsExpected
    // -----------------------------------------------------------------------

    /// <summary>
    /// ClientClosed maps to the Go-compatible "Client Closed" string.
    /// Go reference: server/monitor.go ClosedState.String() case ClientClosed.
    /// </summary>
    [Fact]
    public void ToReasonString_ClientClosed_ReturnsExpected()
    {
        ClosedReasonHelper.ToReasonString(ClosedReason.ClientClosed).ShouldBe("Client Closed");
    }

    // -----------------------------------------------------------------------
    // 2. ToReasonString_AllReasonsHaveStrings
    // -----------------------------------------------------------------------

    /// <summary>
    /// Every ClosedReason enum value must produce a non-null, non-empty string.
    /// Go reference: server/monitor.go ClosedState.String() — all cases covered.
    /// </summary>
    [Fact]
    public void ToReasonString_AllReasonsHaveStrings()
    {
        foreach (var reason in Enum.GetValues<ClosedReason>())
        {
            var s = ClosedReasonHelper.ToReasonString(reason);
            s.ShouldNotBeNull();
            s.ShouldNotBeEmpty();
        }
    }

    // -----------------------------------------------------------------------
    // 3. FromReasonString_ValidString_ReturnsEnum
    // -----------------------------------------------------------------------

    /// <summary>
    /// A valid Go-compatible reason string parses back to the correct enum value.
    /// Go reference: server/monitor.go ClosedState.String() "Server Shutdown".
    /// </summary>
    [Fact]
    public void FromReasonString_ValidString_ReturnsEnum()
    {
        ClosedReasonHelper.FromReasonString("Server Shutdown").ShouldBe(ClosedReason.ServerShutdown);
    }

    // -----------------------------------------------------------------------
    // 4. FromReasonString_Unknown_ReturnsUnknown
    // -----------------------------------------------------------------------

    /// <summary>
    /// An unrecognised string returns ClosedReason.Unknown.
    /// </summary>
    [Fact]
    public void FromReasonString_Unknown_ReturnsUnknown()
    {
        ClosedReasonHelper.FromReasonString("Not a real reason").ShouldBe(ClosedReason.Unknown);
    }

    // -----------------------------------------------------------------------
    // 5. FromReasonString_Null_ReturnsUnknown
    // -----------------------------------------------------------------------

    /// <summary>
    /// A null reason string returns ClosedReason.Unknown.
    /// </summary>
    [Fact]
    public void FromReasonString_Null_ReturnsUnknown()
    {
        ClosedReasonHelper.FromReasonString(null).ShouldBe(ClosedReason.Unknown);
    }

    // -----------------------------------------------------------------------
    // 6. IsClientInitiated_ClientClosed_True
    // -----------------------------------------------------------------------

    /// <summary>
    /// ClientClosed is the only client-initiated close reason.
    /// Go reference: server/client.go closeConnection — client disconnect path.
    /// </summary>
    [Fact]
    public void IsClientInitiated_ClientClosed_True()
    {
        ClosedReasonHelper.IsClientInitiated(ClosedReason.ClientClosed).ShouldBeTrue();
    }

    // -----------------------------------------------------------------------
    // 7. IsClientInitiated_ServerShutdown_False
    // -----------------------------------------------------------------------

    /// <summary>
    /// ServerShutdown is not a client-initiated close.
    /// </summary>
    [Fact]
    public void IsClientInitiated_ServerShutdown_False()
    {
        ClosedReasonHelper.IsClientInitiated(ClosedReason.ServerShutdown).ShouldBeFalse();
    }

    // -----------------------------------------------------------------------
    // 8. IsAuthRelated_AuthTimeout_True
    // -----------------------------------------------------------------------

    /// <summary>
    /// AuthTimeout is auth-related.
    /// Go reference: server/auth.go getAuthErrClosedState — auth timeout path.
    /// </summary>
    [Fact]
    public void IsAuthRelated_AuthTimeout_True()
    {
        ClosedReasonHelper.IsAuthRelated(ClosedReason.AuthTimeout).ShouldBeTrue();
    }

    // -----------------------------------------------------------------------
    // 9. IsAuthRelated_WriteError_False
    // -----------------------------------------------------------------------

    /// <summary>
    /// WriteError is not auth-related.
    /// </summary>
    [Fact]
    public void IsAuthRelated_WriteError_False()
    {
        ClosedReasonHelper.IsAuthRelated(ClosedReason.WriteError).ShouldBeFalse();
    }

    // -----------------------------------------------------------------------
    // 10. IsResourceLimit_MaxConnections_True
    // -----------------------------------------------------------------------

    /// <summary>
    /// MaxConnectionsExceeded is a resource-limit close reason.
    /// Go reference: server/client.go maxConnectionsExceeded — max connections path.
    /// </summary>
    [Fact]
    public void IsResourceLimit_MaxConnections_True()
    {
        ClosedReasonHelper.IsResourceLimit(ClosedReason.MaxConnectionsExceeded).ShouldBeTrue();
    }
}
