// 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;

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; }
}
