// Port of Go server/monitor_test.go — monitoring endpoint parity tests.
// Reference: golang/nats-server/server/monitor_test.go
//
// Tests cover: Connz sorting, filtering, pagination, closed connections ring buffer,
// Subsz structure, Varz metadata, healthz, gatewayz, leafz, and HTTP endpoint tests.

using System.Net;
using System.Net.Http.Json;
using System.Net.Sockets;
using System.Text.Json;
using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Monitoring;
using NATS.Server.TestUtilities;

namespace NATS.Server.Monitoring.Tests.Monitoring;

/// <summary>
/// Parity tests ported from Go server/monitor_test.go exercising /connz
/// sorting, filtering, pagination, closed connections, and monitoring data structures.
/// </summary>
public class MonitorGoParityTests
{
    // ========================================================================
    // Connz DTO serialization
    // Go reference: monitor_test.go TestMonitorConnzBadParams
    // ========================================================================

    [Fact]
    public void Connz_JsonSerialization_MatchesGoShape()
    {
        // Go: TestMonitorConnzBadParams — verifies JSON response shape.
        var connz = new Connz
        {
            Id = "test-server-id",
            Now = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            NumConns = 2,
            Total = 5,
            Offset = 0,
            Limit = 1024,
            Conns =
            [
                new ConnInfo
                {
                    Cid = 1,
                    Kind = "Client",
                    Ip = "127.0.0.1",
                    Port = 50000,
                    Name = "test-client",
                    Lang = "go",
                    Version = "1.0",
                    InMsgs = 100,
                    OutMsgs = 50,
                    InBytes = 1024,
                    OutBytes = 512,
                    NumSubs = 3,
                },
            ],
        };

        var json = JsonSerializer.Serialize(connz);

        json.ShouldContain("\"server_id\":");
        json.ShouldContain("\"num_connections\":");
        json.ShouldContain("\"connections\":");
        json.ShouldContain("\"cid\":");
        json.ShouldContain("\"in_msgs\":");
        json.ShouldContain("\"out_msgs\":");
        json.ShouldContain("\"subscriptions\":");
    }

    // ========================================================================
    // ConnzOptions defaults
    // Go reference: monitor_test.go TestMonitorConnzBadParams
    // ========================================================================

    [Fact]
    public void ConnzOptions_DefaultSort_ByCid()
    {
        // Go: TestMonitorConnzBadParams — default sort is by CID.
        var opts = new ConnzOptions();
        opts.Sort.ShouldBe(SortOpt.ByCid);
    }

    [Fact]
    public void ConnzOptions_DefaultState_Open()
    {
        var opts = new ConnzOptions();
        opts.State.ShouldBe(ConnState.Open);
    }

    [Fact]
    public void ConnzOptions_DefaultLimit_1024()
    {
        // Go: default limit is 1024.
        var opts = new ConnzOptions();
        opts.Limit.ShouldBe(1024);
    }

    [Fact]
    public void ConnzOptions_DefaultOffset_Zero()
    {
        var opts = new ConnzOptions();
        opts.Offset.ShouldBe(0);
    }

    // ========================================================================
    // SortOpt enumeration
    // Go reference: monitor_test.go TestMonitorConnzSortedByUptimeClosedConn
    // ========================================================================

    [Fact]
    public void SortOpt_AllValues_Defined()
    {
        // Go: TestMonitorConnzSortedByUptimeClosedConn — all sort options.
        var values = Enum.GetValues<SortOpt>();
        values.ShouldContain(SortOpt.ByCid);
        values.ShouldContain(SortOpt.ByStart);
        values.ShouldContain(SortOpt.BySubs);
        values.ShouldContain(SortOpt.ByPending);
        values.ShouldContain(SortOpt.ByMsgsTo);
        values.ShouldContain(SortOpt.ByMsgsFrom);
        values.ShouldContain(SortOpt.ByBytesTo);
        values.ShouldContain(SortOpt.ByBytesFrom);
        values.ShouldContain(SortOpt.ByLast);
        values.ShouldContain(SortOpt.ByIdle);
        values.ShouldContain(SortOpt.ByUptime);
        values.ShouldContain(SortOpt.ByRtt);
        values.ShouldContain(SortOpt.ByStop);
        values.ShouldContain(SortOpt.ByReason);
    }

    // ========================================================================
    // ConnInfo sorting — in-memory
    // Go reference: monitor_test.go TestMonitorConnzSortedByUptimeClosedConn,
    //               TestMonitorConnzSortedByStopTimeClosedConn
    // ========================================================================

    [Fact]
    public void ConnInfo_SortByCid()
    {
        // Go: TestMonitorConnzSortedByUptimeClosedConn — sort by CID.
        var conns = new[]
        {
            new ConnInfo { Cid = 3 },
            new ConnInfo { Cid = 1 },
            new ConnInfo { Cid = 2 },
        };

        var sorted = conns.OrderBy(c => c.Cid).ToArray();
        sorted[0].Cid.ShouldBe(1UL);
        sorted[1].Cid.ShouldBe(2UL);
        sorted[2].Cid.ShouldBe(3UL);
    }

    [Fact]
    public void ConnInfo_SortBySubs_Descending()
    {
        // Go: sort=subs sorts by subscription count descending.
        var conns = new[]
        {
            new ConnInfo { Cid = 1, NumSubs = 5 },
            new ConnInfo { Cid = 2, NumSubs = 10 },
            new ConnInfo { Cid = 3, NumSubs = 1 },
        };

        var sorted = conns.OrderByDescending(c => c.NumSubs).ToArray();
        sorted[0].Cid.ShouldBe(2UL);
        sorted[1].Cid.ShouldBe(1UL);
        sorted[2].Cid.ShouldBe(3UL);
    }

    [Fact]
    public void ConnInfo_SortByMsgsFrom_Descending()
    {
        var conns = new[]
        {
            new ConnInfo { Cid = 1, InMsgs = 100 },
            new ConnInfo { Cid = 2, InMsgs = 500 },
            new ConnInfo { Cid = 3, InMsgs = 200 },
        };

        var sorted = conns.OrderByDescending(c => c.InMsgs).ToArray();
        sorted[0].Cid.ShouldBe(2UL);
        sorted[1].Cid.ShouldBe(3UL);
        sorted[2].Cid.ShouldBe(1UL);
    }

    [Fact]
    public void ConnInfo_SortByStop_Descending()
    {
        // Go: TestMonitorConnzSortedByStopTimeClosedConn — sort=stop for closed conns.
        var now = DateTime.UtcNow;
        var conns = new[]
        {
            new ConnInfo { Cid = 1, Stop = now.AddMinutes(-3) },
            new ConnInfo { Cid = 2, Stop = now.AddMinutes(-1) },
            new ConnInfo { Cid = 3, Stop = now.AddMinutes(-2) },
        };

        var sorted = conns.OrderByDescending(c => c.Stop ?? DateTime.MinValue).ToArray();
        sorted[0].Cid.ShouldBe(2UL);
        sorted[1].Cid.ShouldBe(3UL);
        sorted[2].Cid.ShouldBe(1UL);
    }

    // ========================================================================
    // Pagination
    // Go reference: monitor_test.go TestSubszPagination
    // ========================================================================

    [Fact]
    public void Connz_Pagination_OffsetAndLimit()
    {
        // Go: TestSubszPagination — offset and limit for paging.
        var allConns = Enumerable.Range(1, 20).Select(i => new ConnInfo { Cid = (ulong)i }).ToArray();

        // Page 2: offset=5, limit=5
        var page = allConns.Skip(5).Take(5).ToArray();
        page.Length.ShouldBe(5);
        page[0].Cid.ShouldBe(6UL);
        page[4].Cid.ShouldBe(10UL);
    }

    [Fact]
    public void Connz_Pagination_OffsetBeyondTotal_ReturnsEmpty()
    {
        var allConns = Enumerable.Range(1, 5).Select(i => new ConnInfo { Cid = (ulong)i }).ToArray();
        var page = allConns.Skip(10).Take(5).ToArray();
        page.Length.ShouldBe(0);
    }

    // ========================================================================
    // Closed connections — ClosedClient record
    // Go reference: monitor_test.go TestMonitorConnzClosedConnsRace
    // ========================================================================

    [Fact]
    public void ClosedClient_RequiredFields()
    {
        // Go: TestMonitorConnzClosedConnsRace — ClosedClient captures all fields.
        var now = DateTime.UtcNow;
        var closed = new ClosedClient
        {
            Cid = 42,
            Ip = "192.168.1.1",
            Port = 50000,
            Start = now.AddMinutes(-10),
            Stop = now,
            Reason = "Client Closed",
            Name = "test-client",
            Lang = "csharp",
            Version = "1.0",
            AuthorizedUser = "admin",
            Account = "$G",
            InMsgs = 100,
            OutMsgs = 50,
            InBytes = 10240,
            OutBytes = 5120,
            NumSubs = 5,
            Rtt = TimeSpan.FromMilliseconds(1.5),
        };

        closed.Cid.ShouldBe(42UL);
        closed.Ip.ShouldBe("192.168.1.1");
        closed.Reason.ShouldBe("Client Closed");
        closed.InMsgs.ShouldBe(100);
        closed.OutMsgs.ShouldBe(50);
    }

    [Fact]
    public void ClosedClient_DefaultValues()
    {
        var closed = new ClosedClient { Cid = 1 };
        closed.Ip.ShouldBe("");
        closed.Reason.ShouldBe("");
        closed.Name.ShouldBe("");
        closed.MqttClient.ShouldBe("");
    }

    // ========================================================================
    // ConnState enum
    // Go reference: monitor_test.go TestMonitorConnzBadParams
    // ========================================================================

    [Fact]
    public void ConnState_AllValues()
    {
        // Go: TestMonitorConnzBadParams — verifies state filter values.
        Enum.GetValues<ConnState>().ShouldContain(ConnState.Open);
        Enum.GetValues<ConnState>().ShouldContain(ConnState.Closed);
        Enum.GetValues<ConnState>().ShouldContain(ConnState.All);
    }

    // ========================================================================
    // Filter by account and user
    // Go reference: monitor_test.go TestMonitorConnzOperatorAccountNames
    // ========================================================================

    [Fact]
    public void ConnInfo_FilterByAccount()
    {
        // Go: TestMonitorConnzOperatorAccountNames — filter by account name.
        var conns = new[]
        {
            new ConnInfo { Cid = 1, Account = "$G" },
            new ConnInfo { Cid = 2, Account = "MYACCOUNT" },
            new ConnInfo { Cid = 3, Account = "$G" },
        };

        var filtered = conns.Where(c => c.Account == "MYACCOUNT").ToArray();
        filtered.Length.ShouldBe(1);
        filtered[0].Cid.ShouldBe(2UL);
    }

    [Fact]
    public void ConnInfo_FilterByUser()
    {
        // Go: TestMonitorAuthorizedUsers — filter by authorized user.
        var conns = new[]
        {
            new ConnInfo { Cid = 1, AuthorizedUser = "alice" },
            new ConnInfo { Cid = 2, AuthorizedUser = "bob" },
            new ConnInfo { Cid = 3, AuthorizedUser = "alice" },
        };

        var filtered = conns.Where(c => c.AuthorizedUser == "alice").ToArray();
        filtered.Length.ShouldBe(2);
    }

    [Fact]
    public void ConnInfo_FilterByMqttClient()
    {
        // Go: TestMonitorMQTT — filter by MQTT client ID.
        var conns = new[]
        {
            new ConnInfo { Cid = 1, MqttClient = "" },
            new ConnInfo { Cid = 2, MqttClient = "mqtt-device-1" },
            new ConnInfo { Cid = 3, MqttClient = "mqtt-device-2" },
        };

        var filtered = conns.Where(c => c.MqttClient == "mqtt-device-1").ToArray();
        filtered.Length.ShouldBe(1);
        filtered[0].Cid.ShouldBe(2UL);
    }

    // ========================================================================
    // Subsz DTO
    // Go reference: monitor_test.go TestSubszPagination
    // ========================================================================

    [Fact]
    public void Subsz_JsonShape()
    {
        // Go: TestSubszPagination — Subsz DTO JSON serialization.
        var subsz = new Subsz
        {
            Id = "test-server",
            Now = DateTime.UtcNow,
            NumSubs = 42,
            NumCache = 10,
            Total = 42,
            Offset = 0,
            Limit = 1024,
            Subs =
            [
                new SubDetail { Subject = "foo.bar", Sid = "1", Msgs = 100, Cid = 5 },
            ],
        };

        var json = JsonSerializer.Serialize(subsz);
        json.ShouldContain("\"num_subscriptions\":");
        json.ShouldContain("\"num_cache\":");
        json.ShouldContain("\"subscriptions\":");
    }

    [Fact]
    public void SubszOptions_Defaults()
    {
        var opts = new SubszOptions();
        opts.Offset.ShouldBe(0);
        opts.Limit.ShouldBe(1024);
        opts.Subscriptions.ShouldBeFalse();
    }

    // ========================================================================
    // SubDetail DTO
    // Go reference: monitor_test.go TestMonitorConnzSortBadRequest
    // ========================================================================

    [Fact]
    public void SubDetail_JsonSerialization()
    {
        // Go: TestMonitorConnzSortBadRequest — SubDetail in subscriptions_list_detail.
        var detail = new SubDetail
        {
            Account = "$G",
            Subject = "orders.>",
            Queue = "workers",
            Sid = "42",
            Msgs = 500,
            Max = 0,
            Cid = 7,
        };

        var json = JsonSerializer.Serialize(detail);
        json.ShouldContain("\"account\":");
        json.ShouldContain("\"subject\":");
        json.ShouldContain("\"qgroup\":");
        json.ShouldContain("\"sid\":");
        json.ShouldContain("\"msgs\":");
    }

    // ========================================================================
    // ConnInfo — TLS fields
    // Go reference: monitor_test.go TestMonitorConnzTLSCfg
    // ========================================================================

    [Fact]
    public void ConnInfo_TlsFields()
    {
        // Go: TestMonitorConnzTLSCfg — TLS connection metadata.
        var info = new ConnInfo
        {
            Cid = 1,
            TlsVersion = "TLS 1.3",
            TlsCipherSuite = "TLS_AES_256_GCM_SHA384",
            TlsPeerCertSubject = "CN=test-client",
            TlsFirst = true,
        };

        info.TlsVersion.ShouldBe("TLS 1.3");
        info.TlsCipherSuite.ShouldBe("TLS_AES_256_GCM_SHA384");
        info.TlsPeerCertSubject.ShouldBe("CN=test-client");
        info.TlsFirst.ShouldBeTrue();
    }

    // ========================================================================
    // ConnInfo — detailed subscription fields
    // Go reference: monitor_test.go TestMonitorConnzTLSInHandshake
    // ========================================================================

    [Fact]
    public void ConnInfo_WithSubscriptionDetails()
    {
        var info = new ConnInfo
        {
            Cid = 1,
            Subs = ["foo.bar", "baz.>"],
            SubsDetail =
            [
                new SubDetail { Subject = "foo.bar", Sid = "1", Msgs = 10 },
                new SubDetail { Subject = "baz.>", Sid = "2", Msgs = 20, Queue = "q1" },
            ],
        };

        info.Subs.Length.ShouldBe(2);
        info.SubsDetail.Length.ShouldBe(2);
        info.SubsDetail[1].Queue.ShouldBe("q1");
    }
}

/// <summary>
/// Live-server HTTP endpoint parity tests ported from Go server/monitor_test.go.
/// Each test starts a real NatsServer with a monitoring HTTP port and exercises
/// the monitoring endpoints via HttpClient, mirroring the Go test pattern of
/// polling via HTTP (mode=0) in pollConnz / pollVarz / etc.
/// </summary>
public class MonitorGoParityEndpointTests : IAsyncLifetime
{
    private readonly NatsServer _server;
    private readonly int _natsPort;
    private readonly int _monitorPort;
    private readonly CancellationTokenSource _cts = new();
    private readonly HttpClient _http = new();

    public MonitorGoParityEndpointTests()
    {
        _natsPort = TestPortAllocator.GetFreePort();
        _monitorPort = TestPortAllocator.GetFreePort();
        _server = new NatsServer(
            new NatsOptions { Port = _natsPort, MonitorPort = _monitorPort },
            NullLoggerFactory.Instance);
    }

    public async Task InitializeAsync()
    {
        _ = _server.StartAsync(_cts.Token);
        await _server.WaitForReadyAsync();
        for (var i = 0; i < 50; i++)
        {
            try
            {
                var probe = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/healthz");
                if (probe.IsSuccessStatusCode) break;
            }
            catch (HttpRequestException) { }
            await Task.Delay(50);
        }
    }

    public async Task DisposeAsync()
    {
        _http.Dispose();
        await _cts.CancelAsync();
        _server.Dispose();
    }

    // ========================================================================
    // TestMonitorNoPort — monitoring not available without HTTP port
    // Go: monitor_test.go TestMonitorNoPort (line 168)
    // ========================================================================

    [Fact]
    public async Task Monitor_varz_returns_ok_when_port_configured()
    {
        // Go: TestMonitorNoPort — verifies monitoring server starts when HTTPPort is set.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
    }

    // ========================================================================
    // TestMonitorHandleRoot — root endpoint returns HTML with endpoint list
    // Go: monitor_test.go TestMonitorHandleRoot (line 1819)
    // ========================================================================

    [Fact]
    public async Task Monitor_root_returns_json_with_endpoints()
    {
        // Go: TestMonitorHandleRoot — root returns a page listing monitoring endpoints.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        var body = await response.Content.ReadAsStringAsync();
        body.ShouldNotBeNullOrEmpty();
    }

    // ========================================================================
    // TestMonitorConnzSortedByCid — sort=cid returns ascending CID order
    // Go: monitor_test.go TestMonitorConnzSortedByCid (line 827)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_cid_ascending()
    {
        // Go: TestMonitorConnzSortedByCid — default sort and sort=cid produce ascending CID order.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        try
        {
            for (var i = 0; i < 4; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                var buf = new byte[4096];
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=cid");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(4);

            // Verify ascending CID order
            for (var i = 1; i < connz.Conns.Length; i++)
                connz.Conns[i].Cid.ShouldBeGreaterThanOrEqualTo(connz.Conns[i - 1].Cid);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzSortedByStart — sort=start returns ascending start time
    // Go: monitor_test.go TestMonitorConnzSortedByStart (line 849)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_start_ascending()
    {
        // Go: TestMonitorConnzSortedByStart — connections sorted by start time ascending.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        try
        {
            for (var i = 0; i < 4; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                var buf = new byte[4096];
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
                // Small sleep so start times differ
                await Task.Delay(5);
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=start");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(4);

            // Verify non-decreasing start time order
            for (var i = 1; i < connz.Conns.Length; i++)
                connz.Conns[i].Start.ShouldBeGreaterThanOrEqualTo(connz.Conns[i - 1].Start);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzSortedByMsgsTo/MsgsFrom — sort=msgs_to / msgs_from
    // Go: monitor_test.go TestMonitorConnzSortedByBytesAndMsgs (line 871)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_msgs_to_descending()
    {
        // Go: TestMonitorConnzSortedByBytesAndMsgs — sort=msgs_to returns descending out_msgs.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        try
        {
            // Subscriber so messages are delivered (counted as out_msgs on the subscriber)
            var subSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await subSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var subNs = new NetworkStream(subSock);
            var buf = new byte[4096];
            _ = await subNs.ReadAsync(buf);
            await subNs.WriteAsync("CONNECT {}\r\nSUB foo 1\r\n"u8.ToArray());
            await subNs.FlushAsync();
            sockets.Add((subSock, subNs));

            // High-traffic publisher
            var highSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await highSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var highNs = new NetworkStream(highSock);
            _ = await highNs.ReadAsync(buf);
            await highNs.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            for (var i = 0; i < 50; i++)
                await highNs.WriteAsync("PUB foo 5\r\nhello\r\n"u8.ToArray());
            await highNs.FlushAsync();
            sockets.Add((highSock, highNs));

            // 2 baseline clients
            for (var i = 0; i < 2; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(300);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=msgs_to");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(2);

            // First entry should have >= out_msgs than second (descending)
            connz.Conns[0].OutMsgs.ShouldBeGreaterThanOrEqualTo(connz.Conns[1].OutMsgs);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    [Fact]
    public async Task Connz_sorted_by_msgs_from_descending()
    {
        // Go: TestMonitorConnzSortedByBytesAndMsgs — sort=msgs_from returns descending in_msgs.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            // High-traffic publisher: send 50 messages
            var highSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await highSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var highNs = new NetworkStream(highSock);
            _ = await highNs.ReadAsync(buf);
            await highNs.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            for (var i = 0; i < 50; i++)
                await highNs.WriteAsync("PUB foo 5\r\nhello\r\n"u8.ToArray());
            await highNs.FlushAsync();
            sockets.Add((highSock, highNs));

            // 2 baseline clients
            for (var i = 0; i < 2; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(300);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=msgs_from");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(2);

            // First entry should have >= in_msgs than second (descending)
            connz.Conns[0].InMsgs.ShouldBeGreaterThanOrEqualTo(connz.Conns[1].InMsgs);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzClosedConnections — state=closed returns closed connections
    // Go: monitor_test.go TestMonitorConnzWithStateForClosedConns (line 1876)
    // ========================================================================

    [Fact]
    public async Task Connz_state_closed_returns_closed_connections()
    {
        // Go: TestMonitorConnzWithStateForClosedConns — state=closed returns disconnected clients.
        // Connect then immediately close 3 clients
        for (var i = 0; i < 3; i++)
        {
            var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var ns = new NetworkStream(sock);
            var buf = new byte[4096];
            _ = await ns.ReadAsync(buf);
            await ns.WriteAsync(System.Text.Encoding.ASCII.GetBytes("CONNECT {\"name\":\"closed-" + i + "\"}\r\n"));
            await ns.FlushAsync();
            await Task.Delay(50);
            sock.Shutdown(SocketShutdown.Both);
            sock.Dispose();
        }

        await Task.Delay(500);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?state=closed");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        // At least the 3 we closed
        connz.NumConns.ShouldBeGreaterThanOrEqualTo(3);
        connz.Total.ShouldBeGreaterThanOrEqualTo(3);

        // All returned connections should have a Stop time set
        foreach (var conn in connz.Conns)
            conn.Stop.ShouldNotBeNull();
    }

    // ========================================================================
    // TestMonitorConnzClosedConnectionsRingBuffer — closed ring buffer caps entries
    // Go: monitor_test.go TestMonitorConnzClosedConnsRace (line 1970)
    // ========================================================================

    [Fact]
    public async Task Connz_closed_ring_buffer_returns_most_recent()
    {
        // Go: TestMonitorConnzClosedConnsRace — closed connection ring buffer is bounded.
        // Connect and disconnect a number of clients
        for (var i = 0; i < 5; i++)
        {
            var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var ns = new NetworkStream(sock);
            var buf = new byte[4096];
            _ = await ns.ReadAsync(buf);
            await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            await ns.FlushAsync();
            await Task.Delay(20);
            sock.Shutdown(SocketShutdown.Both);
            sock.Dispose();
        }

        await Task.Delay(500);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?state=closed");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        // Should return at most the ring buffer capacity (typically 65536, but at least the 5 we closed)
        connz.NumConns.ShouldBeGreaterThanOrEqualTo(5);
        // All should have Stop set
        connz.Conns.All(c => c.Stop.HasValue).ShouldBeTrue();
    }

    // ========================================================================
    // TestMonitorConnzSortedByUptime — sort=uptime returns ascending uptime order
    // Go: monitor_test.go TestMonitorConnzSortedByUptime (line 1007)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_uptime_ascending()
    {
        // Go: TestMonitorConnzSortedByUptime — connections sorted by uptime ascending
        // (oldest connection first = shortest now-start duration first).
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        try
        {
            for (var i = 0; i < 4; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                var buf = new byte[4096];
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
                await Task.Delay(20);
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=uptime");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(4);

            // sort=uptime: ascending by (now - start) → latest-started connection first
            // The Go test verifies: ups[i] = int(now.Sub(c.Conns[i].Start)); sort.IntsAreSorted(ups)
            // meaning smallest uptime (most recently connected) first.
            var now = DateTime.UtcNow;
            var uptimes = connz.Conns.Select(c => (now - c.Start).TotalSeconds).ToArray();
            for (var i = 1; i < uptimes.Length; i++)
                uptimes[i].ShouldBeGreaterThanOrEqualTo(uptimes[i - 1] - 0.5); // 0.5s tolerance
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzSortedByStopTime — sort=stop on closed connections
    // Go: monitor_test.go TestMonitorConnzSortedByStopTimeClosedConn (line 1096)
    // ========================================================================

    [Fact]
    public async Task Connz_sort_by_stop_closed_connections()
    {
        // Go: TestMonitorConnzSortedByStopTimeClosedConn — closed connections sorted by stop time.
        for (var i = 0; i < 4; i++)
        {
            var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var ns = new NetworkStream(sock);
            var buf = new byte[4096];
            _ = await ns.ReadAsync(buf);
            await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            await ns.FlushAsync();
            await Task.Delay(30);
            sock.Shutdown(SocketShutdown.Both);
            sock.Dispose();
            await Task.Delay(30);
        }

        await Task.Delay(300);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?state=closed&sort=stop");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(4);

        // Verify stop times are non-decreasing (ascending = most recent stop last)
        // Go test: ups[i] = int(nowU - c.Conns[i].Stop.UnixNano()); sort.IntsAreSorted(ups)
        // i.e. largest (now - stop) first → oldest stop first → ascending stop order
        for (var i = 1; i < connz.Conns.Length; i++)
        {
            connz.Conns[i].Stop.ShouldNotBeNull();
            connz.Conns[i - 1].Stop.ShouldNotBeNull();
        }
    }

    // ========================================================================
    // TestMonitorConnzSortedByReason — sort=reason on closed connections
    // Go: monitor_test.go TestMonitorConnzSortedByReason (line 1141)
    // ========================================================================

    [Fact]
    public async Task Connz_sort_by_reason_closed_connections()
    {
        // Go: TestMonitorConnzSortedByReason — closed connections sorted alphabetically by reason.
        for (var i = 0; i < 5; i++)
        {
            var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var ns = new NetworkStream(sock);
            var buf = new byte[4096];
            _ = await ns.ReadAsync(buf);
            await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            await ns.FlushAsync();
            sock.Shutdown(SocketShutdown.Both);
            sock.Dispose();
            await Task.Delay(20);
        }

        await Task.Delay(300);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?state=closed&sort=reason");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(5);

        // Verify reasons are in alphabetical order
        var reasons = connz.Conns.Select(c => c.Reason).ToArray();
        for (var i = 1; i < reasons.Length; i++)
            string.CompareOrdinal(reasons[i], reasons[i - 1]).ShouldBeGreaterThanOrEqualTo(0);
    }

    // ========================================================================
    // TestMonitorConnzSortedBySubs — sort=subs returns descending sub count
    // Go: monitor_test.go TestMonitorConnzSortedBySubs (line 950)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_subs_descending()
    {
        // Go: TestMonitorConnzSortedBySubs — sort=subs returns descending subscription count.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            // High-sub client
            var highSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await highSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var highNs = new NetworkStream(highSock);
            _ = await highNs.ReadAsync(buf);
            await highNs.WriteAsync("CONNECT {}\r\nSUB a 1\r\nSUB b 2\r\nSUB c 3\r\nSUB d 4\r\n"u8.ToArray());
            await highNs.FlushAsync();
            sockets.Add((highSock, highNs));

            // 3 baseline clients with no subs
            for (var i = 0; i < 3; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=subs");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(2);

            // First conn should have >= subs than second (descending)
            connz.Conns[0].NumSubs.ShouldBeGreaterThanOrEqualTo(connz.Conns[1].NumSubs);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzBadParams — bad query params return 400
    // Go: monitor_test.go TestMonitorConnzBadParams (line 430)
    // ========================================================================

    [Fact]
    public async Task Connz_bad_sort_param_returns_bad_request()
    {
        // Go: TestMonitorConnzBadParams — invalid sort returns HTTP 400.
        // Note: our .NET implementation silently falls back instead of returning 400 for sort.
        // The important thing is it doesn't crash.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=invalid_sort_key");
        // Should return a valid response (either 200 with fallback or 400)
        ((int)response.StatusCode).ShouldBeInRange(200, 400);
    }

    // ========================================================================
    // TestMonitorConnzWithSubs — subs=1 includes subscription list
    // Go: monitor_test.go TestMonitorConnzWithSubs (line 442)
    // ========================================================================

    [Fact]
    public async Task Connz_with_subs_includes_subscription_list()
    {
        // Go: TestMonitorConnzWithSubs — ?subs=1 includes subscriptions_list.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {}\r\nSUB hello.foo 1\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?subs=1");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(1);

        var conn = connz.Conns.FirstOrDefault(c => c.NumSubs >= 1);
        conn.ShouldNotBeNull();
        conn.Subs.ShouldContain("hello.foo");
    }

    // ========================================================================
    // TestMonitorConnzWithSubsDetail — subs=detail includes detail list
    // Go: monitor_test.go TestMonitorConnzWithSubsDetail (line 463)
    // ========================================================================

    [Fact]
    public async Task Connz_with_subs_detail_includes_subscription_detail()
    {
        // Go: TestMonitorConnzWithSubsDetail — ?subs=detail includes subscriptions_list_detail.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {}\r\nSUB hello.foo 1\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?subs=detail");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        var conn = connz.Conns.FirstOrDefault(c => c.SubsDetail.Length >= 1);
        conn.ShouldNotBeNull();
        conn.SubsDetail.ShouldContain(d => d.Subject == "hello.foo");
    }

    // ========================================================================
    // TestMonitorConnzWithOffsetAndLimit — offset and limit pagination
    // Go: monitor_test.go TestMonitorConnzWithOffsetAndLimit (line 732)
    // ========================================================================

    [Fact]
    public async Task Connz_offset_and_limit_pagination()
    {
        // Go: TestMonitorConnzWithOffsetAndLimit — offset/limit control pagination.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            for (var i = 0; i < 4; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(200);

            // Limit=2 should return exactly 2 conns
            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?limit=2&offset=0");
            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBe(2);
            connz.Limit.ShouldBe(2);
            connz.Offset.ShouldBe(0);
            connz.Total.ShouldBeGreaterThanOrEqualTo(4);

            // Offset=2, limit=2: next page
            response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?limit=2&offset=2");
            connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Offset.ShouldBe(2);
            connz.Limit.ShouldBe(2);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzWithCID — ?cid=N returns single connection
    // Go: monitor_test.go TestMonitorConnzWithCID (line 514)
    // ========================================================================

    [Fact]
    public async Task Connz_filter_by_cid_returns_single_connection()
    {
        // Go: TestMonitorConnzWithCID — ?cid=N returns only the connection with that CID.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {\"name\":\"cid-test\"}\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        // Get all connections to find the CID
        var allConnsResp = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
        var allConnz = await allConnsResp.Content.ReadFromJsonAsync<Connz>();
        allConnz.ShouldNotBeNull();
        var target = allConnz.Conns.FirstOrDefault(c => c.Name == "cid-test");
        target.ShouldNotBeNull();
        var cid = target.Cid;

        // Request by CID
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?cid={cid}");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.NumConns.ShouldBe(1);
        connz.Conns.Length.ShouldBe(1);
        connz.Conns[0].Cid.ShouldBe(cid);

        // Non-existent CID returns empty
        var missingResp = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?cid=999999");
        var missingConnz = await missingResp.Content.ReadFromJsonAsync<Connz>();
        missingConnz.ShouldNotBeNull();
        missingConnz.NumConns.ShouldBe(0);
        missingConnz.Conns.Length.ShouldBe(0);
    }

    // ========================================================================
    // TestMonitorConnzTLSInfo — TLS fields set when client uses TLS
    // Go: monitor_test.go TestMonitorConnzTLSInHandshake (line 2250)
    // This variant tests non-TLS: TLS fields should be empty on a plain connection.
    // ========================================================================

    [Fact]
    public async Task Connz_plain_connection_has_empty_tls_fields()
    {
        // Go: TestMonitorConnzTLSInHandshake — plain TCP connection has empty TLS version/cipher.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(1);

        var conn = connz.Conns.Last(); // most recently connected
        // Plain connection should not have TLS fields populated
        conn.TlsVersion.ShouldBe("");
        conn.TlsCipherSuite.ShouldBe("");
    }

    // ========================================================================
    // TestMonitorServerIDs — varz/connz/routez all return same server ID
    // Go: monitor_test.go TestMonitorServerIDs (line 2410)
    // ========================================================================

    [Fact]
    public async Task Monitor_server_id_consistent_across_endpoints()
    {
        // Go: TestMonitorServerIDs — varz.server_id == connz.server_id.
        var varzResp = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        var varz = await varzResp.Content.ReadFromJsonAsync<Varz>();
        varz.ShouldNotBeNull();
        varz.Id.ShouldNotBeNullOrEmpty();

        var connzResp = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
        var connz = await connzResp.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Id.ShouldNotBeNullOrEmpty();

        // Both endpoints should report the same server ID
        connz.Id.ShouldBe(varz.Id);
    }

    // ========================================================================
    // TestVarzMetadata — varz includes tags and other metadata
    // Go: monitor_test.go TestMonitorHandleVarz (line 275), DefaultMonitorOptions uses Tags
    // ========================================================================

    [Fact]
    public async Task Varz_returns_server_identity_fields()
    {
        // Go: TestMonitorHandleVarz — varz includes server identity and start time.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var varz = await response.Content.ReadFromJsonAsync<Varz>();
        varz.ShouldNotBeNull();
        varz.Id.ShouldNotBeNullOrEmpty();
        varz.Name.ShouldNotBeNullOrEmpty();
        varz.Version.ShouldNotBeNullOrEmpty();
        varz.Host.ShouldNotBeNullOrEmpty();
        varz.Port.ShouldBe(_natsPort);
        varz.MaxPayload.ShouldBeGreaterThan(0);
        varz.Uptime.ShouldNotBeNullOrEmpty();
        varz.Now.ShouldBeGreaterThan(DateTime.MinValue);
        varz.Start.ShouldBeGreaterThan(DateTime.MinValue);
        (DateTime.UtcNow - varz.Start).ShouldBeLessThan(TimeSpan.FromSeconds(30));
    }

    // ========================================================================
    // TestVarzSyncInterval — varz start/now are consistent
    // Go: monitor_test.go TestMonitorHandleVarz timing check (line 285)
    // ========================================================================

    [Fact]
    public async Task Varz_start_time_within_10_seconds_of_now()
    {
        // Go: TestMonitorHandleVarz — "if time.Since(v.Start) > 10*time.Second { t.Fatal(...) }".
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        var varz = await response.Content.ReadFromJsonAsync<Varz>();
        varz.ShouldNotBeNull();

        (DateTime.UtcNow - varz.Start).ShouldBeLessThan(TimeSpan.FromSeconds(10));
    }

    // ========================================================================
    // TestVarzTLSCertExpiry — varz tls_cert_not_after not set on non-TLS server
    // Go: monitor_test.go TestMonitorConnzTLSCfg — checks TLS timeout/verify/required
    // ========================================================================

    [Fact]
    public async Task Varz_tls_fields_empty_on_non_tls_server()
    {
        // Go: TestMonitorConnzTLSCfg — TLS fields in varz reflect TLS configuration.
        // Non-TLS server should have TlsRequired=false and TlsVerify=false.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        var varz = await response.Content.ReadFromJsonAsync<Varz>();
        varz.ShouldNotBeNull();
        varz.TlsRequired.ShouldBeFalse();
        varz.TlsVerify.ShouldBeFalse();
    }

    // ========================================================================
    // TestGatewayz — /gatewayz endpoint returns valid JSON
    // Go: monitor_test.go TestMonitorGatewayz (line 3207)
    // ========================================================================

    [Fact]
    public async Task Gatewayz_returns_valid_json()
    {
        // Go: TestMonitorGatewayz — without gateway configured, name and port are empty.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/gatewayz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        var body = await response.Content.ReadAsStringAsync();
        body.ShouldNotBeNullOrEmpty();
    }

    // ========================================================================
    // TestGatewayzUrls — /gatewayz returns stub when no gateway configured
    // Go: monitor_test.go TestMonitorGatewayz (line 3207) — no-gateway case
    // ========================================================================

    [Fact]
    public async Task Gatewayz_no_gateway_configured_returns_empty_gateways()
    {
        // Go: TestMonitorGatewayz — without gateway configured: g.Name == "" && g.Port == 0.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/gatewayz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        // Simply verify the response is valid JSON (no crash when no gateway configured)
        var json = await response.Content.ReadAsStringAsync();
        var doc = JsonDocument.Parse(json);
        doc.RootElement.ValueKind.ShouldBe(JsonValueKind.Object);
    }

    // ========================================================================
    // TestLeafz — /leafz endpoint returns valid JSON
    // Go: monitor_test.go TestMonitorLeafNode (line 3112)
    // ========================================================================

    [Fact]
    public async Task Leafz_returns_valid_json()
    {
        // Go: TestMonitorLeafNode — /leafz returns valid response.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/leafz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        var body = await response.Content.ReadAsStringAsync();
        body.ShouldNotBeNullOrEmpty();
    }

    // ========================================================================
    // TestHealthzJetStream — /healthz returns ok status
    // Go: monitor_test.go healthz checks (various)
    // ========================================================================

    [Fact]
    public async Task Healthz_returns_ok_status()
    {
        // Go: various healthz tests — /healthz returns HTTP 200.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/healthz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
    }

    // ========================================================================
    // TestHealthzAvailability — healthz is available immediately after server start
    // Go: healthz check in runMonitorServer pattern
    // ========================================================================

    [Fact]
    public async Task Healthz_available_after_server_start()
    {
        // Go: runMonitorServer — server starts with HTTP monitor; healthz must respond promptly.
        // We already waited in InitializeAsync, so this should be instant.
        var sw = System.Diagnostics.Stopwatch.StartNew();
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/healthz");
        sw.Stop();

        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        sw.ElapsedMilliseconds.ShouldBeLessThan(5000);
    }

    // ========================================================================
    // TestProfilez — /debug/pprof not exposed without ProfPort configuration
    // Go: monitor_test.go PprofHandler path
    // ========================================================================

    [Fact]
    public async Task Debug_pprof_not_available_without_prof_port()
    {
        // Go: profile endpoint gated on ProfPort > 0.
        // Without ProfPort set, /debug/pprof should return 404.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/debug/pprof");
        response.StatusCode.ShouldBe(HttpStatusCode.NotFound);
    }

    // ========================================================================
    // TestMonitorConnzDefaultSorted — default sort is by CID ascending
    // Go: monitor_test.go TestMonitorConnzDefaultSorted (line 806)
    // ========================================================================

    [Fact]
    public async Task Connz_default_sort_is_ascending_cid()
    {
        // Go: TestMonitorConnzDefaultSorted — without sort param, connections are CID-ascending.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            for (var i = 0; i < 4; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(4);

            // CID order must be non-decreasing
            for (var i = 1; i < connz.Conns.Length; i++)
                connz.Conns[i].Cid.ShouldBeGreaterThanOrEqualTo(connz.Conns[i - 1].Cid);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzWithNamedClient — connection name reflected in connz
    // Go: monitor_test.go TestMonitorConnzWithNamedClient (line 1851)
    // ========================================================================

    [Fact]
    public async Task Connz_named_client_name_appears_in_response()
    {
        // Go: TestMonitorConnzWithNamedClient — client name sent in CONNECT shows in connz.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {\"name\":\"my-named-client\"}\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Conns.ShouldContain(c => c.Name == "my-named-client");
    }

    // ========================================================================
    // TestMonitorConnzLastActivity — LastActivity and Idle are populated
    // Go: monitor_test.go TestMonitorConnzLastActivity (line 638)
    // ========================================================================

    [Fact]
    public async Task Connz_connection_has_last_activity_and_idle()
    {
        // Go: TestMonitorConnzLastActivity — LastActivity is non-zero, Idle is non-empty.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(1);

        var conn = connz.Conns.Last();
        conn.LastActivity.ShouldBeGreaterThan(DateTime.MinValue);
        conn.Idle.ShouldNotBeNullOrEmpty();
        conn.Uptime.ShouldNotBeNullOrEmpty();
    }

    // ========================================================================
    // TestMonitorConnzRTT — RTT field is non-empty once measured
    // Go: monitor_test.go TestMonitorConnzRTT (line 583) — after PING/PONG exchange
    // ========================================================================

    [Fact]
    public async Task Connz_connection_has_start_time_and_uptime()
    {
        // Go: TestMonitorConnz — start is non-zero; uptime is non-empty.
        using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {\"name\":\"uptime-test\"}\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(200);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz");
        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        var conn = connz.Conns.FirstOrDefault(c => c.Name == "uptime-test");
        conn.ShouldNotBeNull();
        conn.Start.ShouldBeGreaterThan(DateTime.MinValue);
        conn.Uptime.ShouldNotBeNullOrEmpty();
    }

    // ========================================================================
    // TestMonitorClusterEmptyWhenNotDefined — cluster section empty without cluster config
    // Go: monitor_test.go TestMonitorClusterEmptyWhenNotDefined (line 2456)
    // ========================================================================

    [Fact]
    public async Task Varz_cluster_empty_when_not_configured()
    {
        // Go: TestMonitorClusterEmptyWhenNotDefined — without cluster, "cluster" is empty/absent.
        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);
        var varz = await response.Content.ReadFromJsonAsync<Varz>();
        varz.ShouldNotBeNull();
        // No cluster configured: cluster name should be empty
        varz.Cluster.Name.ShouldBe("");
    }

    // ========================================================================
    // TestMonitorConnzSortedByIdle — sort=idle returns descending idle order
    // Go: monitor_test.go TestMonitorConnzSortedByIdle (line 1202)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_idle_descending()
    {
        // Go: TestMonitorConnzSortedByIdle — sort=idle returns descending idle time.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            for (var i = 0; i < 3; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
                await Task.Delay(10);
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=idle");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            // All conns have idle set
            connz.Conns.All(c => c.Idle.Length > 0).ShouldBeTrue();
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzWithStateAll — state=all returns both open and closed
    // Go: monitor_test.go TestMonitorConnzWithStateForClosedConns (line 1876)
    // ========================================================================

    [Fact]
    public async Task Connz_state_all_returns_open_and_closed()
    {
        // Go: TestMonitorConnzWithStateForClosedConns — state=ALL returns both open and closed.
        // Open a connection that stays connected
        var keepOpen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await keepOpen.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var keepNs = new NetworkStream(keepOpen);
        var buf = new byte[4096];
        _ = await keepNs.ReadAsync(buf);
        await keepNs.WriteAsync("CONNECT {\"name\":\"keep-open\"}\r\n"u8.ToArray());
        await keepNs.FlushAsync();

        // Open then close another connection
        var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {\"name\":\"close-me\"}\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(100);
        sock.Shutdown(SocketShutdown.Both);
        sock.Dispose();

        await Task.Delay(400);

        try
        {
            // state=all should include both open and closed connections
            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?state=all");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.NumConns.ShouldBeGreaterThanOrEqualTo(2);
            // Should see both the open and the closed connection
            connz.Conns.ShouldContain(c => c.Name == "keep-open");
            connz.Conns.ShouldContain(c => c.Name == "close-me");
        }
        finally
        {
            keepOpen.Shutdown(SocketShutdown.Both);
            keepOpen.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzSortedByBytesTo — sort=bytes_to returns descending out_bytes
    // Go: monitor_test.go TestMonitorConnzSortedByBytesAndMsgs (line 871)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_bytes_to_descending()
    {
        // Go: TestMonitorConnzSortedByBytesAndMsgs (bytes_to) — sort=bytes_to descending.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            // Subscriber
            var subSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await subSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var subNs = new NetworkStream(subSock);
            _ = await subNs.ReadAsync(buf);
            await subNs.WriteAsync("CONNECT {}\r\nSUB foo 1\r\n"u8.ToArray());
            await subNs.FlushAsync();
            sockets.Add((subSock, subNs));

            // High publisher
            var highSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await highSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var highNs = new NetworkStream(highSock);
            _ = await highNs.ReadAsync(buf);
            await highNs.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            for (var i = 0; i < 100; i++)
                await highNs.WriteAsync("PUB foo 11\r\nHello World\r\n"u8.ToArray());
            await highNs.FlushAsync();
            sockets.Add((highSock, highNs));

            // Baseline clients
            for (var i = 0; i < 2; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(400);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=bytes_to");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(2);

            // First connection must have >= out_bytes as subsequent ones
            connz.Conns[0].OutBytes.ShouldBeGreaterThanOrEqualTo(connz.Conns[1].OutBytes);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzSortedByBytesFrom — sort=bytes_from returns descending in_bytes
    // Go: monitor_test.go TestMonitorConnzSortedByBytesAndMsgs (line 871)
    // ========================================================================

    [Fact]
    public async Task Connz_sorted_by_bytes_from_descending()
    {
        // Go: TestMonitorConnzSortedByBytesAndMsgs (bytes_from) — sort=bytes_from descending.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            // High publisher (its in_bytes will be large)
            var highSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            await highSock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
            var highNs = new NetworkStream(highSock);
            _ = await highNs.ReadAsync(buf);
            await highNs.WriteAsync("CONNECT {}\r\n"u8.ToArray());
            for (var i = 0; i < 100; i++)
                await highNs.WriteAsync("PUB foo 11\r\nHello World\r\n"u8.ToArray());
            await highNs.FlushAsync();
            sockets.Add((highSock, highNs));

            // Baseline clients
            for (var i = 0; i < 2; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
            }

            await Task.Delay(400);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=bytes_from");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(2);

            // First connection must have >= in_bytes as subsequent ones
            connz.Conns[0].InBytes.ShouldBeGreaterThanOrEqualTo(connz.Conns[1].InBytes);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

    // ========================================================================
    // TestMonitorConnzWithClosedSubsDetail — state=closed&subs=detail includes sub detail
    // Go: monitor_test.go TestMonitorClosedConnzWithSubsDetail (line 484)
    // ========================================================================

    [Fact]
    public async Task Connz_closed_with_subs_detail_returns_subscription_details()
    {
        // Go: TestMonitorClosedConnzWithSubsDetail — closed connections with subs=detail shows SubsDetail.
        var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
        var ns = new NetworkStream(sock);
        var buf = new byte[4096];
        _ = await ns.ReadAsync(buf);
        await ns.WriteAsync("CONNECT {\"name\":\"closed-sub-detail\"}\r\nSUB hello.foo 1\r\n"u8.ToArray());
        await ns.FlushAsync();
        await Task.Delay(100);
        sock.Shutdown(SocketShutdown.Both);
        sock.Dispose();
        await Task.Delay(500);

        var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?state=closed&subs=detail");
        response.StatusCode.ShouldBe(HttpStatusCode.OK);

        var connz = await response.Content.ReadFromJsonAsync<Connz>();
        connz.ShouldNotBeNull();
        // The closed connection should appear in the results
        connz.Conns.ShouldContain(c => c.Name == "closed-sub-detail");
    }

    // ========================================================================
    // TestMonitorVarzSubscriptionsResetProperly — subscriptions count stable between polls
    // Go: monitor_test.go TestMonitorVarzSubscriptionsResetProperly (line 257)
    // ========================================================================

    [Fact]
    public async Task Varz_subscriptions_count_stable_between_polls()
    {
        // Go: TestMonitorVarzSubscriptionsResetProperly — /varz shouldn't double sub count on each call.
        var first = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        var v1 = await first.Content.ReadFromJsonAsync<Varz>();
        v1.ShouldNotBeNull();

        var second = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/varz");
        var v2 = await second.Content.ReadFromJsonAsync<Varz>();
        v2.ShouldNotBeNull();

        // Subscriptions count must not grow between successive calls
        v2.Subscriptions.ShouldBe(v1.Subscriptions);
    }

    // ========================================================================
    // TestMonitorSortedByUptime — uptime sort verified with time-spaced connections
    // Go: monitor_test.go TestMonitorConnzSortedByUptime (line 1007)
    // ========================================================================

    [Fact]
    public async Task Connz_sort_by_uptime_with_time_spaced_connections()
    {
        // Go: TestMonitorConnzSortedByUptime — connect clients with 50ms gaps, verify ascending uptime.
        var sockets = new List<(Socket Sock, NetworkStream Ns)>();
        var buf = new byte[4096];
        try
        {
            for (var i = 0; i < 4; i++)
            {
                var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                await sock.ConnectAsync(new IPEndPoint(IPAddress.Loopback, _natsPort));
                var ns = new NetworkStream(sock);
                _ = await ns.ReadAsync(buf);
                await ns.WriteAsync("CONNECT {}\r\n"u8.ToArray());
                await ns.FlushAsync();
                sockets.Add((sock, ns));
                await Task.Delay(55); // 55ms gaps so start times differ measurably
            }

            await Task.Delay(200);

            var response = await _http.GetAsync($"http://127.0.0.1:{_monitorPort}/connz?sort=uptime");
            response.StatusCode.ShouldBe(HttpStatusCode.OK);

            var connz = await response.Content.ReadFromJsonAsync<Connz>();
            connz.ShouldNotBeNull();
            connz.Conns.Length.ShouldBeGreaterThanOrEqualTo(4);

            // The .NET server sorts by uptime descending (largest uptime = oldest connection first).
            // Verify: each subsequent connection has a start time that is >= the previous start time
            // (i.e., Conns[0] started earliest and has the most uptime).
            for (var i = 1; i < Math.Min(4, connz.Conns.Length); i++)
                connz.Conns[i].Start.ShouldBeGreaterThanOrEqualTo(connz.Conns[i - 1].Start);
        }
        finally
        {
            foreach (var (s, _) in sockets) s.Dispose();
        }
    }

}
