using System.Text.Json.Serialization;

namespace NATS.Server.Monitoring;

/// <summary>
/// Connection information response. Corresponds to Go server/monitor.go Connz struct.
/// </summary>
public sealed class Connz
{
    [JsonPropertyName("server_id")]
    public string Id { get; set; } = "";

    [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 ConnInfo[] Conns { get; set; } = [];
}

/// <summary>
/// Detailed information on a per-connection basis.
/// Corresponds to Go server/monitor.go ConnInfo struct.
/// </summary>
public sealed class ConnInfo
{
    [JsonPropertyName("cid")]
    public ulong Cid { get; set; }

    [JsonPropertyName("kind")]
    public string Kind { get; set; } = "";

    [JsonPropertyName("type")]
    public string Type { get; set; } = "";

    [JsonPropertyName("ip")]
    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("stop")]
    public DateTime? Stop { get; set; }

    [JsonPropertyName("reason")]
    public string Reason { get; set; } = "";

    [JsonPropertyName("rtt")]
    public string Rtt { get; set; } = "";

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

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

    [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("subscriptions")]
    public uint NumSubs { get; set; }

    [JsonPropertyName("subscriptions_list")]
    public string[] Subs { get; set; } = [];

    [JsonPropertyName("subscriptions_list_detail")]
    public SubDetail[] SubsDetail { get; set; } = [];

    [JsonPropertyName("name")]
    public string Name { get; set; } = "";

    [JsonPropertyName("lang")]
    public string Lang { get; set; } = "";

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

    [JsonPropertyName("authorized_user")]
    public string AuthorizedUser { get; set; } = "";

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

    [JsonPropertyName("tls_version")]
    public string TlsVersion { get; set; } = "";

    [JsonPropertyName("tls_cipher_suite")]
    public string TlsCipherSuite { get; set; } = "";

    [JsonPropertyName("tls_peer_cert_subject")]
    public string TlsPeerCertSubject { get; set; } = "";

    [JsonPropertyName("tls_first")]
    public bool TlsFirst { get; set; }

    [JsonPropertyName("mqtt_client")]
    public string MqttClient { get; set; } = "";

    [JsonPropertyName("jwt_issuer_key")]
    public string JwtIssuerKey { get; set; } = "";

    [JsonPropertyName("jwt_tags")]
    public string JwtTags { get; set; } = "";

    [JsonPropertyName("proxy")]
    public string Proxy { get; set; } = "";
}

/// <summary>
/// Subscription detail information.
/// Corresponds to Go server/monitor.go SubDetail struct.
/// </summary>
public sealed class SubDetail
{
    [JsonPropertyName("account")]
    public string Account { get; set; } = "";

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

    [JsonPropertyName("qgroup")]
    public string Queue { get; set; } = "";

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

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

    [JsonPropertyName("max")]
    public long Max { get; set; }

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

/// <summary>
/// Sort options for connection listing.
/// Corresponds to Go server/monitor_sort_opts.go SortOpt type.
/// </summary>
public enum SortOpt
{
    ByCid,
    ByStart,
    BySubs,
    ByPending,
    ByMsgsTo,
    ByMsgsFrom,
    ByBytesTo,
    ByBytesFrom,
    ByLast,
    ByIdle,
    ByUptime,
    ByRtt,
    ByStop,
    ByReason,
}

/// <summary>
/// Connection state filter.
/// Corresponds to Go server/monitor.go ConnState type.
/// </summary>
public enum ConnState
{
    Open,
    Closed,
    All,
}

/// <summary>
/// Options passed to Connz() for filtering and sorting.
/// Corresponds to Go server/monitor.go ConnzOptions struct.
/// </summary>
public sealed class ConnzOptions
{
    public SortOpt Sort { get; set; } = SortOpt.ByCid;

    public bool Subscriptions { get; set; }

    public bool SubscriptionsDetail { get; set; }

    public ConnState State { get; set; } = ConnState.Open;

    public string User { get; set; } = "";

    public string Account { get; set; } = "";

    public string FilterSubject { get; set; } = "";

    public string MqttClient { get; set; } = "";

    /// <summary>
    /// When non-zero, returns only the connection with this CID.
    /// Go reference: monitor.go ConnzOptions.CID.
    /// </summary>
    public ulong Cid { get; set; }

    /// <summary>
    /// Whether to include authorized user info.
    /// Go reference: monitor.go ConnzOptions.Username.
    /// </summary>
    public bool Auth { get; set; }

    public int Offset { get; set; }

    public int Limit { get; set; } = 1024;
}
