// Copyright 2013-2026 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Adapted from server/monitor.go in the NATS server Go source.

using System.Text.Json.Serialization;
using ZB.MOM.NatsNet.Server.Auth;
using ZB.MOM.NatsNet.Server.Internal.DataStructures;

namespace ZB.MOM.NatsNet.Server;

// ============================================================================
// Monitor list size defaults
// Mirrors Go const block near top of monitor.go.
// ============================================================================

/// <summary>
/// Default sizes for monitoring API response lists.
/// Mirrors Go constants in server/monitor.go.
/// </summary>
public static class MonitorDefaults
{
    /// <summary>Default maximum number of connection entries returned. Mirrors Go <c>DefaultConnListSize = 1024</c>.</summary>
    public const int DefaultConnListSize = 1024;

    /// <summary>Default maximum number of subscription entries returned. Mirrors Go <c>DefaultSubListSize = 1024</c>.</summary>
    public const int DefaultSubListSize  = 1024;
}

// ============================================================================
// ConnState — connection state filter for Connz queries
// Mirrors Go <c>ConnState</c> and its iota constants in monitor.go.
// ============================================================================

/// <summary>
/// Filter applied to connection-list queries to select open, closed, or
/// all connections.
/// Mirrors Go <c>ConnState</c> in server/monitor.go.
/// </summary>
public enum ConnState
{
    /// <summary>Only return open (active) connections. Mirrors Go <c>ConnOpen = 0</c>.</summary>
    ConnOpen   = 0,

    /// <summary>Only return closed connections. Mirrors Go <c>ConnClosed</c>.</summary>
    ConnClosed = 1,

    /// <summary>Return all connections, open or closed. Mirrors Go <c>ConnAll</c>.</summary>
    ConnAll    = 2,
}

// ============================================================================
// ConnzOptions — query options for the Connz endpoint
// Mirrors Go <c>ConnzOptions</c> struct in server/monitor.go.
// ============================================================================

/// <summary>
/// Options that control the output of a <c>Connz</c> monitoring query.
/// Mirrors Go <c>ConnzOptions</c> struct in server/monitor.go.
/// </summary>
public sealed class ConnzOptions
{
    /// <summary>
    /// How to sort results. Only <c>ByCid</c> is ascending; all others are
    /// descending. Mirrors Go <c>Sort SortOpt</c>.
    /// </summary>
    [JsonPropertyName("sort")]
    public SortOpt Sort { get; set; } = SortOpt.ByCid;

    /// <summary>When true, usernames are included in results. Mirrors Go <c>Username bool</c>.</summary>
    [JsonPropertyName("auth")]
    public bool Username { get; set; }

    /// <summary>When true, subscription subjects are listed. Mirrors Go <c>Subscriptions bool</c>.</summary>
    [JsonPropertyName("subscriptions")]
    public bool Subscriptions { get; set; }

    /// <summary>When true, verbose subscription detail is included. Mirrors Go <c>SubscriptionsDetail bool</c>.</summary>
    [JsonPropertyName("subscriptions_detail")]
    public bool SubscriptionsDetail { get; set; }

    /// <summary>Zero-based offset for pagination. Mirrors Go <c>Offset int</c>.</summary>
    [JsonPropertyName("offset")]
    public int Offset { get; set; }

    /// <summary>Maximum number of connections to return. Mirrors Go <c>Limit int</c>.</summary>
    [JsonPropertyName("limit")]
    public int Limit { get; set; }

    /// <summary>Filter for a specific client connection by CID. Mirrors Go <c>CID uint64</c>.</summary>
    [JsonPropertyName("cid")]
    public ulong Cid { get; set; }

    /// <summary>Filter for a specific MQTT client ID. Mirrors Go <c>MQTTClient string</c>.</summary>
    [JsonPropertyName("mqtt_client")]
    public string MqttClient { get; set; } = string.Empty;

    /// <summary>Connection state filter. Mirrors Go <c>State ConnState</c>.</summary>
    [JsonPropertyName("state")]
    public ConnState State { get; set; } = ConnState.ConnOpen;

    /// <summary>Filter by username. Mirrors Go <c>User string</c>.</summary>
    [JsonPropertyName("user")]
    public string User { get; set; } = string.Empty;

    /// <summary>Filter by account name. Mirrors Go <c>Account string</c>.</summary>
    [JsonPropertyName("acc")]
    public string Account { get; set; } = string.Empty;

    /// <summary>Filter by subject interest (requires Account filter). Mirrors Go <c>FilterSubject string</c>.</summary>
    [JsonPropertyName("filter_subject")]
    public string FilterSubject { get; set; } = string.Empty;
}

// ============================================================================
// Connz — top-level connection list monitoring response
// Mirrors Go <c>Connz</c> struct in server/monitor.go.
// ============================================================================

/// <summary>
/// Top-level response type for the <c>/connz</c> monitoring endpoint.
/// Contains the current connection list and pagination metadata.
/// Mirrors Go <c>Connz</c> struct in server/monitor.go.
/// </summary>
public sealed class Connz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    [JsonPropertyName("num_connections")]
    public int NumConns { get; set; }

    [JsonPropertyName("total")]
    public int Total { get; set; }

    [JsonPropertyName("offset")]
    public int Offset { get; set; }

    [JsonPropertyName("limit")]
    public int Limit { get; set; }

    [JsonPropertyName("connections")]
    public List<ConnInfo> Conns { get; set; } = [];
}

// ============================================================================
// ConnInfo — per-connection detail record
// Mirrors Go <c>ConnInfo</c> struct in server/monitor.go.
// ============================================================================

/// <summary>
/// Detailed information about a single client connection, as returned by the
/// <c>/connz</c> monitoring endpoint.
/// Mirrors Go <c>ConnInfo</c> struct in server/monitor.go.
/// </summary>
public sealed class ConnInfo
{
    [JsonPropertyName("cid")]
    public ulong Cid { get; set; }

    [JsonPropertyName("kind")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Kind { get; set; }

    [JsonPropertyName("type")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Type { get; set; }

    [JsonPropertyName("ip")]
    public string Ip { get; set; } = string.Empty;

    [JsonPropertyName("port")]
    public int Port { get; set; }

    [JsonPropertyName("start")]
    public DateTime Start { get; set; }

    [JsonPropertyName("last_activity")]
    public DateTime LastActivity { get; set; }

    [JsonPropertyName("stop")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public DateTime? Stop { get; set; }

    [JsonPropertyName("reason")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Reason { get; set; }

    [JsonPropertyName("rtt")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Rtt { get; set; }

    [JsonPropertyName("uptime")]
    public string Uptime { get; set; } = string.Empty;

    [JsonPropertyName("idle")]
    public string Idle { get; set; } = string.Empty;

    [JsonPropertyName("pending_bytes")]
    public int Pending { get; set; }

    [JsonPropertyName("in_msgs")]
    public long InMsgs { get; set; }

    [JsonPropertyName("out_msgs")]
    public long OutMsgs { get; set; }

    [JsonPropertyName("in_bytes")]
    public long InBytes { get; set; }

    [JsonPropertyName("out_bytes")]
    public long OutBytes { get; set; }

    [JsonPropertyName("stalls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Stalls { get; set; }

    [JsonPropertyName("subscriptions")]
    public uint NumSubs { get; set; }

    [JsonPropertyName("name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonPropertyName("lang")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Lang { get; set; }

    [JsonPropertyName("version")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Version { get; set; }

    [JsonPropertyName("tls_version")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? TlsVersion { get; set; }

    [JsonPropertyName("tls_cipher_suite")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? TlsCipher { get; set; }

    [JsonPropertyName("tls_peer_certs")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<TlsPeerCert>? TlsPeerCerts { get; set; }

    [JsonPropertyName("tls_first")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsFirst { get; set; }

    [JsonPropertyName("authorized_user")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? AuthorizedUser { get; set; }

    [JsonPropertyName("account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Account { get; set; }

    [JsonPropertyName("subscriptions_list")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Subs { get; set; }

    [JsonPropertyName("subscriptions_list_detail")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<SubDetail>? SubsDetail { get; set; }

    [JsonPropertyName("jwt")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Jwt { get; set; }

    [JsonPropertyName("issuer_key")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? IssuerKey { get; set; }

    [JsonPropertyName("name_tag")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? NameTag { get; set; }

    [JsonPropertyName("tags")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string[]? Tags { get; set; }

    [JsonPropertyName("mqtt_client")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? MqttClient { get; set; }

    [JsonPropertyName("proxy")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public ProxyInfo? Proxy { get; set; }

    /// <summary>
    /// Internal field used for fast RTT-based sorting.
    /// Mirrors Go <c>rtt int64</c> unexported field in ConnInfo.
    /// Not serialised.
    /// </summary>
    [JsonIgnore]
    internal long RttNanos { get; set; }
}

// ============================================================================
// ProxyInfo — proxy connection metadata
// Mirrors Go <c>ProxyInfo</c> struct in server/monitor.go.
// ============================================================================

/// <summary>
/// Information about a proxied connection (e.g. HAProxy PROXY protocol).
/// Mirrors Go <c>ProxyInfo</c> struct in server/monitor.go.
/// </summary>
public sealed class ProxyInfo
{
    [JsonPropertyName("key")]
    public string Key { get; set; } = string.Empty;
}

// ============================================================================
// TlsPeerCert — TLS peer certificate summary
// Mirrors Go <c>TLSPeerCert</c> struct in server/monitor.go.
// ============================================================================

/// <summary>
/// Basic information about a TLS peer certificate.
/// Mirrors Go <c>TLSPeerCert</c> struct in server/monitor.go.
/// </summary>
public sealed class TlsPeerCert
{
    [JsonPropertyName("subject")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Subject { get; set; }

    [JsonPropertyName("spki_sha256")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? SubjectPkiSha256 { get; set; }

    [JsonPropertyName("cert_sha256")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? CertSha256 { get; set; }
}

// ============================================================================
// SubDetail — verbose subscription information
// Mirrors Go <c>SubDetail</c> struct in server/monitor.go (line ~961).
// ============================================================================

/// <summary>
/// Verbose information about a single subscription, included in detailed
/// connection or account monitoring responses.
/// Mirrors Go <c>SubDetail</c> struct in server/monitor.go.
/// </summary>
public sealed class SubDetail
{
    [JsonPropertyName("account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Account { get; set; }

    [JsonPropertyName("account_tag")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? AccountTag { get; set; }

    [JsonPropertyName("subject")]
    public string Subject { get; set; } = string.Empty;

    [JsonPropertyName("qgroup")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Queue { get; set; }

    [JsonPropertyName("sid")]
    public string Sid { get; set; } = string.Empty;

    [JsonPropertyName("msgs")]
    public long Msgs { get; set; }

    [JsonPropertyName("max")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Max { get; set; }

    [JsonPropertyName("cid")]
    public ulong Cid { get; set; }
}

// ============================================================================
// Route monitoring types (Routez, RoutezOptions, RouteInfo)
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>
/// Options that control the output of a <c>Routez</c> monitoring query.
/// Mirrors Go <c>RoutezOptions</c> in server/monitor.go.
/// </summary>
public sealed class RoutezOptions
{
    [JsonPropertyName("subscriptions")]
    public bool Subscriptions { get; set; }

    [JsonPropertyName("subscriptions_detail")]
    public bool SubscriptionsDetail { get; set; }
}

/// <summary>
/// Top-level response type for the <c>/routez</c> monitoring endpoint.
/// Mirrors Go <c>Routez</c> in server/monitor.go.
/// </summary>
public sealed class Routez
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("server_name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    [JsonPropertyName("import")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public SubjectPermission? Import { get; set; }

    [JsonPropertyName("export")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public SubjectPermission? Export { get; set; }

    [JsonPropertyName("num_routes")]
    public int NumRoutes { get; set; }

    [JsonPropertyName("routes")]
    public List<RouteMonitorInfo> Routes { get; set; } = [];
}

/// <summary>
/// Per-route detail record for the <c>/routez</c> monitoring endpoint.
/// Mirrors Go <c>RouteInfo</c> in server/monitor.go.
/// </summary>
public sealed class RouteMonitorInfo
{
    [JsonPropertyName("rid")]
    public ulong Rid { get; set; }

    [JsonPropertyName("remote_id")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? RemoteId { get; set; }

    [JsonPropertyName("remote_name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? RemoteName { get; set; }

    [JsonPropertyName("did_solicit")]
    public bool DidSolicit { get; set; }

    [JsonPropertyName("is_configured")]
    public bool IsConfigured { get; set; }

    [JsonPropertyName("ip")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Ip { get; set; }

    [JsonPropertyName("port")]
    public int Port { get; set; }

    [JsonPropertyName("start")]
    public DateTime Start { get; set; }

    [JsonPropertyName("last_activity")]
    public DateTime LastActivity { get; set; }

    [JsonPropertyName("rtt")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Rtt { get; set; }

    [JsonPropertyName("uptime")]
    public string Uptime { get; set; } = string.Empty;

    [JsonPropertyName("idle")]
    public string Idle { get; set; } = string.Empty;

    [JsonPropertyName("import")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public SubjectPermission? Import { get; set; }

    [JsonPropertyName("export")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public SubjectPermission? Export { get; set; }

    [JsonPropertyName("pending_size")]
    public int Pending { get; set; }

    [JsonPropertyName("in_msgs")]
    public long InMsgs { get; set; }

    [JsonPropertyName("out_msgs")]
    public long OutMsgs { get; set; }

    [JsonPropertyName("in_bytes")]
    public long InBytes { get; set; }

    [JsonPropertyName("out_bytes")]
    public long OutBytes { get; set; }

    [JsonPropertyName("subscriptions")]
    public uint NumSubs { get; set; }

    [JsonPropertyName("subscriptions_list")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Subs { get; set; }

    [JsonPropertyName("subscriptions_list_detail")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<SubDetail>? SubsDetail { get; set; }

    [JsonPropertyName("account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Account { get; set; }

    [JsonPropertyName("compression")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Compression { get; set; }
}

// ============================================================================
// Subsz — subscription list monitoring types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>
/// Options for the <c>/subsz</c> monitoring endpoint.
/// Mirrors Go <c>SubszOptions</c> in server/monitor.go.
/// </summary>
public sealed class SubszOptions
{
    [JsonPropertyName("offset")]
    public int Offset { get; set; }

    [JsonPropertyName("limit")]
    public int Limit { get; set; }

    [JsonPropertyName("subscriptions")]
    public bool Subscriptions { get; set; }

    [JsonPropertyName("account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Account { get; set; }

    [JsonPropertyName("test")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Test { get; set; }
}

/// <summary>
/// Top-level response for the <c>/subsz</c> monitoring endpoint.
/// Mirrors Go <c>Subsz</c> in server/monitor.go.
/// </summary>
public sealed class Subsz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    // SublistStats fields inlined
    [JsonPropertyName("num_subscriptions")]
    public uint NumSubs { get; set; }

    [JsonPropertyName("num_cache")]
    public uint NumCache { get; set; }

    [JsonPropertyName("num_inserts")]
    public ulong NumInserts { get; set; }

    [JsonPropertyName("num_removes")]
    public ulong NumRemoves { get; set; }

    [JsonPropertyName("num_matches")]
    public ulong NumMatches { get; set; }

    [JsonPropertyName("cache_hit_rate")]
    public double CacheHitRate { get; set; }

    [JsonPropertyName("max_fanout")]
    public uint MaxFanout { get; set; }

    [JsonPropertyName("avg_fanout")]
    public double AvgFanout { get; set; }

    [JsonPropertyName("total")]
    public int Total { get; set; }

    [JsonPropertyName("offset")]
    public int Offset { get; set; }

    [JsonPropertyName("limit")]
    public int Limit { get; set; }

    [JsonPropertyName("subscriptions_list")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<SubDetail>? Subs { get; set; }
}

// ============================================================================
// Gatewayz types (GatewayzOptions, Gatewayz, RemoteGatewayz, AccountGatewayz)
// are defined in MonitorHelpers.cs to avoid duplication.

// ============================================================================
// Leafz — leaf-node monitoring types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for <c>/leafz</c>. Mirrors Go <c>LeafzOptions</c>.</summary>
public sealed class LeafzOptions
{
    [JsonPropertyName("subscriptions")]
    public bool Subscriptions { get; set; }

    [JsonPropertyName("account")]
    public string Account { get; set; } = string.Empty;
}

/// <summary>Top-level response for <c>/leafz</c>. Mirrors Go <c>Leafz</c>.</summary>
public sealed class Leafz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    [JsonPropertyName("leafnodes")]
    public int NumLeafs { get; set; }

    [JsonPropertyName("leafs")]
    public List<LeafInfo> Leafs { get; set; } = [];
}

/// <summary>Per-leaf info record. Mirrors Go <c>LeafInfo</c>.</summary>
public sealed class LeafInfo
{
    [JsonPropertyName("id")]
    public ulong Id { get; set; }

    [JsonPropertyName("name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonPropertyName("is_spoke")]
    public bool IsSpoke { get; set; }

    [JsonPropertyName("is_isolated")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool IsIsolated { get; set; }

    [JsonPropertyName("account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Account { get; set; }

    [JsonPropertyName("ip")]
    public string Ip { get; set; } = string.Empty;

    [JsonPropertyName("port")]
    public int Port { get; set; }

    [JsonPropertyName("rtt")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Rtt { get; set; }

    [JsonPropertyName("in_msgs")]
    public long InMsgs { get; set; }

    [JsonPropertyName("out_msgs")]
    public long OutMsgs { get; set; }

    [JsonPropertyName("in_bytes")]
    public long InBytes { get; set; }

    [JsonPropertyName("out_bytes")]
    public long OutBytes { get; set; }

    [JsonPropertyName("subscriptions")]
    public uint NumSubs { get; set; }

    [JsonPropertyName("subscriptions_list")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Subs { get; set; }

    [JsonPropertyName("compression")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Compression { get; set; }

    [JsonPropertyName("proxy")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public ProxyInfo? Proxy { get; set; }
}

// ============================================================================
// AccountStatz — account statistics monitoring types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for <c>/accstatz</c>. Mirrors Go <c>AccountStatzOptions</c>.</summary>
public sealed class AccountStatzOptions
{
    [JsonPropertyName("accounts")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Accounts { get; set; }

    [JsonPropertyName("include_unused")]
    public bool IncludeUnused { get; set; }
}

/// <summary>Top-level response for <c>/accstatz</c>. Mirrors Go <c>AccountStatz</c>.</summary>
public sealed class AccountStatz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    [JsonPropertyName("account_statz")]
    public List<AccountStat> Accounts { get; set; } = [];
}

// ============================================================================
// Accountz — account detail monitoring types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for <c>/accountz</c>. Mirrors Go <c>AccountzOptions</c>.</summary>
public sealed class AccountzOptions
{
    [JsonPropertyName("account")]
    public string Account { get; set; } = string.Empty;
}

/// <summary>Top-level response for <c>/accountz</c>. Mirrors Go <c>Accountz</c>.</summary>
public sealed class Accountz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    [JsonPropertyName("system_account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? SystemAccount { get; set; }

    [JsonPropertyName("accounts")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Accounts { get; set; }

    [JsonPropertyName("account_detail")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public AccountInfo? Account { get; set; }
}

/// <summary>Detailed account information. Mirrors Go <c>AccountInfo</c>.</summary>
public sealed class AccountInfo
{
    [JsonPropertyName("account_name")]
    public string AccountName { get; set; } = string.Empty;

    [JsonPropertyName("update_time")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public DateTime LastUpdate { get; set; }

    [JsonPropertyName("is_system")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool IsSystem { get; set; }

    [JsonPropertyName("expired")]
    public bool Expired { get; set; }

    [JsonPropertyName("complete")]
    public bool Complete { get; set; }

    [JsonPropertyName("jetstream_enabled")]
    public bool JetStream { get; set; }

    [JsonPropertyName("leafnode_connections")]
    public int LeafCnt { get; set; }

    [JsonPropertyName("client_connections")]
    public int ClientCnt { get; set; }

    [JsonPropertyName("subscriptions")]
    public uint SubCnt { get; set; }

    [JsonPropertyName("sublist_stats")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public SublistStats? Sublist { get; set; }
}

// ============================================================================
// Varz — server information types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for <c>/varz</c>. Currently no fields. Mirrors Go <c>VarzOptions</c>.</summary>
public sealed class VarzOptions { }

/// <summary>
/// Top-level response for the <c>/varz</c> monitoring endpoint.
/// Mirrors Go <c>Varz</c> in server/monitor.go.
/// </summary>
public sealed class Varz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("server_name")]
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("version")]
    public string Version { get; set; } = string.Empty;

    [JsonPropertyName("proto")]
    public int Proto { get; set; }

    [JsonPropertyName("git_commit")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? GitCommit { get; set; }

    [JsonPropertyName("go")]
    public string GoVersion { get; set; } = string.Empty;

    [JsonPropertyName("host")]
    public string Host { get; set; } = string.Empty;

    [JsonPropertyName("port")]
    public int Port { get; set; }

    [JsonPropertyName("auth_required")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool AuthRequired { get; set; }

    [JsonPropertyName("tls_required")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsRequired { get; set; }

    [JsonPropertyName("tls_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsVerify { get; set; }

    [JsonPropertyName("tls_ocsp_peer_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsOcspPeerVerify { get; set; }

    [JsonPropertyName("ip")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Ip { get; set; }

    [JsonPropertyName("connect_urls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? ClientConnectUrls { get; set; }

    [JsonPropertyName("ws_connect_urls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? WsConnectUrls { get; set; }

    [JsonPropertyName("max_connections")]
    public int MaxConn { get; set; }

    [JsonPropertyName("max_subscriptions")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int MaxSubs { get; set; }

    [JsonPropertyName("ping_interval")]
    public long PingIntervalNs { get; set; }

    [JsonPropertyName("ping_max")]
    public int MaxPingsOut { get; set; }

    [JsonPropertyName("http_host")]
    public string HttpHost { get; set; } = string.Empty;

    [JsonPropertyName("http_port")]
    public int HttpPort { get; set; }

    [JsonPropertyName("http_base_path")]
    public string HttpBasePath { get; set; } = string.Empty;

    [JsonPropertyName("https_port")]
    public int HttpsPort { get; set; }

    [JsonPropertyName("auth_timeout")]
    public double AuthTimeout { get; set; }

    [JsonPropertyName("max_control_line")]
    public int MaxControlLine { get; set; }

    [JsonPropertyName("max_payload")]
    public int MaxPayload { get; set; }

    [JsonPropertyName("max_pending")]
    public long MaxPending { get; set; }

    [JsonPropertyName("cluster")]
    public ClusterOptsVarz Cluster { get; set; } = new();

    [JsonPropertyName("gateway")]
    public GatewayOptsVarz Gateway { get; set; } = new();

    [JsonPropertyName("leaf")]
    public LeafNodeOptsVarz LeafNode { get; set; } = new();

    [JsonPropertyName("mqtt")]
    public MqttOptsVarz Mqtt { get; set; } = new();

    [JsonPropertyName("websocket")]
    public WebsocketOptsVarz Websocket { get; set; } = new();

    [JsonPropertyName("jetstream")]
    public JetStreamVarz JetStream { get; set; } = new();

    [JsonPropertyName("tls_timeout")]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("write_deadline")]
    public long WriteDeadlineNs { get; set; }

    [JsonPropertyName("write_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? WriteTimeout { get; set; }

    [JsonPropertyName("start")]
    public DateTime Start { get; set; }

    [JsonPropertyName("now")]
    public DateTime Now { get; set; }

    [JsonPropertyName("uptime")]
    public string Uptime { get; set; } = string.Empty;

    [JsonPropertyName("mem")]
    public long Mem { get; set; }

    [JsonPropertyName("cores")]
    public int Cores { get; set; }

    [JsonPropertyName("gomaxprocs")]
    public int MaxProcs { get; set; }

    [JsonPropertyName("cpu")]
    public double Cpu { get; set; }

    [JsonPropertyName("connections")]
    public int Connections { get; set; }

    [JsonPropertyName("total_connections")]
    public ulong TotalConnections { get; set; }

    [JsonPropertyName("routes")]
    public int Routes { get; set; }

    [JsonPropertyName("remotes")]
    public int Remotes { get; set; }

    [JsonPropertyName("leafnodes")]
    public int Leafs { get; set; }

    [JsonPropertyName("in_msgs")]
    public long InMsgs { get; set; }

    [JsonPropertyName("out_msgs")]
    public long OutMsgs { get; set; }

    [JsonPropertyName("in_bytes")]
    public long InBytes { get; set; }

    [JsonPropertyName("out_bytes")]
    public long OutBytes { get; set; }

    [JsonPropertyName("slow_consumers")]
    public long SlowConsumers { get; set; }

    [JsonPropertyName("stale_connections")]
    public long StaleConnections { get; set; }

    [JsonPropertyName("stalled_clients")]
    public long StalledClients { get; set; }

    [JsonPropertyName("subscriptions")]
    public uint Subscriptions { get; set; }

    [JsonPropertyName("http_req_stats")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public Dictionary<string, ulong>? HttpReqStats { get; set; }

    [JsonPropertyName("config_load_time")]
    public DateTime ConfigLoadTime { get; set; }

    [JsonPropertyName("config_digest")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? ConfigDigest { get; set; }

    [JsonPropertyName("tags")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string[]? Tags { get; set; }

    [JsonPropertyName("metadata")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public Dictionary<string, string>? Metadata { get; set; }

    [JsonPropertyName("system_account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? SystemAccount { get; set; }

    [JsonPropertyName("pinned_account_fails")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public ulong PinnedAccountFail { get; set; }

    [JsonPropertyName("ocsp_peer_cache")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public OcspResponseCacheVarz? OcspResponseCache { get; set; }

    [JsonPropertyName("slow_consumer_stats")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public SlowConsumersStats? SlowConsumersStats { get; set; }

    [JsonPropertyName("stale_connection_stats")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public StaleConnectionStats? StaleConnectionStats { get; set; }
}

/// <summary>JetStream section of /varz. Mirrors Go <c>JetStreamVarz</c>.</summary>
public sealed class JetStreamVarz
{
    [JsonPropertyName("config")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public object? Config { get; set; }

    [JsonPropertyName("stats")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public object? Stats { get; set; }

    [JsonPropertyName("meta")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public MetaClusterInfo? Meta { get; set; }

    [JsonPropertyName("limits")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public object? Limits { get; set; }
}

/// <summary>Meta cluster info for JetStream. Mirrors Go <c>MetaClusterInfo</c>.</summary>
public sealed class MetaClusterInfo
{
    [JsonPropertyName("name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonPropertyName("leader")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Leader { get; set; }

    [JsonPropertyName("peer")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Peer { get; set; }

    [JsonPropertyName("replicas")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public object? Replicas { get; set; }

    [JsonPropertyName("cluster_size")]
    public int Size { get; set; }

    [JsonPropertyName("pending")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Pending { get; set; }
}

/// <summary>Cluster section of /varz. Mirrors Go <c>ClusterOptsVarz</c>.</summary>
public sealed class ClusterOptsVarz
{
    [JsonPropertyName("name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonPropertyName("addr")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Host { get; set; }

    [JsonPropertyName("cluster_port")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Port { get; set; }

    [JsonPropertyName("auth_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double AuthTimeout { get; set; }

    [JsonPropertyName("urls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Urls { get; set; }

    [JsonPropertyName("tls_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("tls_required")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsRequired { get; set; }

    [JsonPropertyName("tls_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsVerify { get; set; }

    [JsonPropertyName("pool_size")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int PoolSize { get; set; }

    [JsonPropertyName("write_deadline")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long WriteDeadlineNs { get; set; }

    [JsonPropertyName("write_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? WriteTimeout { get; set; }
}

/// <summary>Gateway section of /varz. Mirrors Go <c>GatewayOptsVarz</c>.</summary>
public sealed class GatewayOptsVarz
{
    [JsonPropertyName("name")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonPropertyName("host")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Host { get; set; }

    [JsonPropertyName("port")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Port { get; set; }

    [JsonPropertyName("auth_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double AuthTimeout { get; set; }

    [JsonPropertyName("tls_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("tls_required")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsRequired { get; set; }

    [JsonPropertyName("tls_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsVerify { get; set; }

    [JsonPropertyName("advertise")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Advertise { get; set; }

    [JsonPropertyName("connect_retries")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int ConnectRetries { get; set; }

    [JsonPropertyName("gateways")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<RemoteGatewayOptsVarz>? Gateways { get; set; }

    [JsonPropertyName("reject_unknown")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool RejectUnknown { get; set; }
}

/// <summary>Remote gateway options in /varz. Mirrors Go <c>RemoteGatewayOptsVarz</c>.</summary>
public sealed class RemoteGatewayOptsVarz
{
    [JsonPropertyName("name")]
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("tls_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("urls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Urls { get; set; }
}

/// <summary>Leaf node section of /varz. Mirrors Go <c>LeafNodeOptsVarz</c>.</summary>
public sealed class LeafNodeOptsVarz
{
    [JsonPropertyName("host")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Host { get; set; }

    [JsonPropertyName("port")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Port { get; set; }

    [JsonPropertyName("auth_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double AuthTimeout { get; set; }

    [JsonPropertyName("tls_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("tls_required")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsRequired { get; set; }

    [JsonPropertyName("tls_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsVerify { get; set; }

    [JsonPropertyName("remotes")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<RemoteLeafOptsVarz>? Remotes { get; set; }

    [JsonPropertyName("tls_ocsp_peer_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsOcspPeerVerify { get; set; }
}

/// <summary>Deny rules for leaf-node remotes. Mirrors Go <c>DenyRules</c>.</summary>
public sealed class DenyRules
{
    [JsonPropertyName("exports")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Exports { get; set; }

    [JsonPropertyName("imports")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Imports { get; set; }
}

/// <summary>Remote leaf options entry in /varz. Mirrors Go <c>RemoteLeafOptsVarz</c>.</summary>
public sealed class RemoteLeafOptsVarz
{
    [JsonPropertyName("local_account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? LocalAccount { get; set; }

    [JsonPropertyName("tls_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("urls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? Urls { get; set; }

    [JsonPropertyName("deny")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public DenyRules? Deny { get; set; }

    [JsonPropertyName("tls_ocsp_peer_verify")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsOcspPeerVerify { get; set; }
}

/// <summary>MQTT section of /varz. Mirrors Go <c>MQTTOptsVarz</c>.</summary>
public sealed class MqttOptsVarz
{
    [JsonPropertyName("host")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Host { get; set; }

    [JsonPropertyName("port")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Port { get; set; }

    [JsonPropertyName("no_auth_user")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? NoAuthUser { get; set; }

    [JsonPropertyName("auth_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double AuthTimeout { get; set; }

    [JsonPropertyName("tls_map")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsMap { get; set; }

    [JsonPropertyName("tls_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double TlsTimeout { get; set; }

    [JsonPropertyName("js_domain")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? JsDomain { get; set; }

    [JsonPropertyName("ack_wait")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long AckWaitNs { get; set; }

    [JsonPropertyName("max_ack_pending")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public ushort MaxAckPending { get; set; }
}

/// <summary>WebSocket section of /varz. Mirrors Go <c>WebsocketOptsVarz</c>.</summary>
public sealed class WebsocketOptsVarz
{
    [JsonPropertyName("host")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Host { get; set; }

    [JsonPropertyName("port")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Port { get; set; }

    [JsonPropertyName("advertise")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Advertise { get; set; }

    [JsonPropertyName("no_auth_user")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? NoAuthUser { get; set; }

    [JsonPropertyName("jwt_cookie")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? JwtCookie { get; set; }

    [JsonPropertyName("auth_timeout")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public double AuthTimeout { get; set; }

    [JsonPropertyName("no_tls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool NoTls { get; set; }

    [JsonPropertyName("tls_map")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool TlsMap { get; set; }

    [JsonPropertyName("same_origin")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool SameOrigin { get; set; }

    [JsonPropertyName("allowed_origins")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<string>? AllowedOrigins { get; set; }

    [JsonPropertyName("compression")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool Compression { get; set; }
}

/// <summary>OCSP response cache summary for /varz. Mirrors Go <c>OCSPResponseCacheVarz</c>.</summary>
public sealed class OcspResponseCacheVarz
{
    [JsonPropertyName("cache_type")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Type { get; set; }

    [JsonPropertyName("cache_hits")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Hits { get; set; }

    [JsonPropertyName("cache_misses")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Misses { get; set; }

    [JsonPropertyName("cached_responses")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Responses { get; set; }

    [JsonPropertyName("cached_revoked_responses")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Revokes { get; set; }

    [JsonPropertyName("cached_good_responses")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Goods { get; set; }

    [JsonPropertyName("cached_unknown_responses")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public long Unknowns { get; set; }
}

// SlowConsumersStats and StaleConnectionStats are defined in Events/EventTypes.cs.

// ============================================================================
// Healthz types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for <c>/healthz</c>. Mirrors Go <c>HealthzOptions</c>.</summary>
public sealed class HealthzOptions
{
    public bool JSEnabled { get; set; }
    public bool JSEnabledOnly { get; set; }
    public bool JSServerOnly { get; set; }
    public bool JSMetaOnly { get; set; }
    public string Account { get; set; } = string.Empty;
    public string Stream { get; set; } = string.Empty;
    public string Consumer { get; set; } = string.Empty;
    public bool Details { get; set; }
}

/// <summary>Health status response. Mirrors Go <c>HealthStatus</c>.</summary>
public sealed class HealthStatus
{
    [JsonPropertyName("status")]
    public string Status { get; set; } = "ok";

    [JsonPropertyName("status_code")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int StatusCode { get; set; }

    [JsonPropertyName("error")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Error { get; set; }

    [JsonPropertyName("errors")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public List<HealthzError>? Errors { get; set; }
}

/// <summary>Individual health check error. Mirrors Go <c>HealthzError</c>.</summary>
public sealed class HealthzError
{
    [JsonPropertyName("type")]
    public HealthZErrorType Type { get; set; }

    [JsonPropertyName("account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Account { get; set; }

    [JsonPropertyName("stream")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Stream { get; set; }

    [JsonPropertyName("consumer")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Consumer { get; set; }

    [JsonPropertyName("error")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Error { get; set; }
}

/// <summary>
/// Healthz error type enum with JSON-as-string serialization.
/// Mirrors Go <c>HealthZErrorType</c> in server/monitor.go.
/// </summary>
[JsonConverter(typeof(HealthZErrorTypeConverter))]
public enum HealthZErrorType
{
    Conn        = 0,
    BadRequest  = 1,
    JetStream   = 2,
    Account     = 3,
    Stream      = 4,
    Consumer    = 5,
}

/// <summary>
/// JSON converter for <see cref="HealthZErrorType"/> — serialises as uppercase string.
/// </summary>
public sealed class HealthZErrorTypeConverter : System.Text.Json.Serialization.JsonConverter<HealthZErrorType>
{
    public override HealthZErrorType Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
        var s = reader.GetString();
        return s switch
        {
            "CONNECTION"  => HealthZErrorType.Conn,
            "BAD_REQUEST" => HealthZErrorType.BadRequest,
            "JETSTREAM"   => HealthZErrorType.JetStream,
            "ACCOUNT"     => HealthZErrorType.Account,
            "STREAM"      => HealthZErrorType.Stream,
            "CONSUMER"    => HealthZErrorType.Consumer,
            _             => throw new System.Text.Json.JsonException($"Unknown HealthZErrorType: {s}")
        };
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, HealthZErrorType value, System.Text.Json.JsonSerializerOptions options)
    {
        var s = value switch
        {
            HealthZErrorType.Conn        => "CONNECTION",
            HealthZErrorType.BadRequest  => "BAD_REQUEST",
            HealthZErrorType.JetStream   => "JETSTREAM",
            HealthZErrorType.Account     => "ACCOUNT",
            HealthZErrorType.Stream      => "STREAM",
            HealthZErrorType.Consumer    => "CONSUMER",
            _                            => "unknown"
        };
        writer.WriteStringValue(s);
    }
}

// ============================================================================
// Expvarz, Profilez types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Response from /debug/vars. Mirrors Go <c>ExpvarzStatus</c>.</summary>
public sealed class ExpvarzStatus
{
    [JsonPropertyName("memstats")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public System.Text.Json.JsonElement? Memstats { get; set; }

    [JsonPropertyName("cmdline")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public System.Text.Json.JsonElement? Cmdline { get; set; }
}

/// <summary>Options for /profilez. Mirrors Go <c>ProfilezOptions</c>.</summary>
public sealed class ProfilezOptions
{
    public string Name { get; set; } = string.Empty;
    public int Debug { get; set; }
    public TimeSpan Duration { get; set; }
}

/// <summary>Response from /profilez. Mirrors Go <c>ProfilezStatus</c>.</summary>
public sealed class ProfilezStatus
{
    [JsonPropertyName("profile")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public byte[]? Profile { get; set; }

    [JsonPropertyName("error")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Error { get; set; }
}

// ============================================================================
// Raftz types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for /raftz. Mirrors Go <c>RaftzOptions</c>.</summary>
public sealed class RaftzOptions
{
    public string AccountFilter { get; set; } = string.Empty;
    public string GroupFilter { get; set; } = string.Empty;
}

/// <summary>Per-peer info for a raft group. Mirrors Go <c>RaftzGroupPeer</c>.</summary>
public sealed class RaftzGroupPeer
{
    [JsonPropertyName("name")]
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("known")]
    public bool Known { get; set; }

    [JsonPropertyName("last_replicated_index")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public ulong LastReplicatedIndex { get; set; }

    [JsonPropertyName("last_seen")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? LastSeen { get; set; }
}

/// <summary>Per-group detail for a raft node. Mirrors Go <c>RaftzGroup</c>.</summary>
public sealed class RaftzGroup
{
    [JsonPropertyName("id")]
    public string Id { get; set; } = string.Empty;

    [JsonPropertyName("state")]
    public string State { get; set; } = string.Empty;

    [JsonPropertyName("size")]
    public int Size { get; set; }

    [JsonPropertyName("quorum_needed")]
    public int QuorumNeeded { get; set; }

    [JsonPropertyName("observer")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool Observer { get; set; }

    [JsonPropertyName("paused")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool Paused { get; set; }

    [JsonPropertyName("committed")]
    public ulong Committed { get; set; }

    [JsonPropertyName("applied")]
    public ulong Applied { get; set; }

    [JsonPropertyName("catching_up")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public bool CatchingUp { get; set; }

    [JsonPropertyName("leader")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Leader { get; set; }

    [JsonPropertyName("leader_since")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public DateTime? LeaderSince { get; set; }

    [JsonPropertyName("ever_had_leader")]
    public bool EverHadLeader { get; set; }

    [JsonPropertyName("term")]
    public ulong Term { get; set; }

    [JsonPropertyName("voted_for")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Vote { get; set; }

    [JsonPropertyName("pterm")]
    public ulong PTerm { get; set; }

    [JsonPropertyName("pindex")]
    public ulong PIndex { get; set; }

    [JsonPropertyName("system_account")]
    public bool SystemAcc { get; set; }

    [JsonPropertyName("traffic_account")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? TrafficAcc { get; set; }

    [JsonPropertyName("peers")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public Dictionary<string, RaftzGroupPeer>? Peers { get; set; }
}

/// <summary>Top-level /raftz response. Mirrors Go <c>RaftzStatus map[string]map[string]RaftzGroup</c>.</summary>
public sealed class RaftzStatus : Dictionary<string, Dictionary<string, RaftzGroup>>
{
    public RaftzStatus() : base(StringComparer.Ordinal) { }
}

// ============================================================================
// IpQueuesz types
// Mirrors Go types in server/monitor.go.
// ============================================================================

/// <summary>Options for /ipqueuesz. Mirrors Go <c>IpqueueszOptions</c>.</summary>
public sealed class IpqueueszOptions
{
    public bool All { get; set; }
    public string Filter { get; set; } = string.Empty;
}

/// <summary>Per-queue entry in /ipqueuesz response. Mirrors Go <c>IpqueueszStatusIPQ</c>.</summary>
public sealed class IpqueueszStatusIpq
{
    [JsonPropertyName("pending")]
    public int Pending { get; set; }

    [JsonPropertyName("in_progress")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int InProgress { get; set; }
}

/// <summary>Top-level /ipqueuesz response — a dictionary of queue name to status. Mirrors Go <c>IpqueueszStatus</c>.</summary>
public sealed class IpqueueszStatus : Dictionary<string, IpqueueszStatusIpq>
{
    public IpqueueszStatus() : base(StringComparer.Ordinal) { }
}
