// Copyright 2012-2025 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/opts.go in the NATS server Go source.

using System.Net.Security;
using System.Security.Authentication;
using System.Text.Json.Serialization;
using System.Threading;
using ZB.MOM.NatsNet.Server.Auth;

namespace ZB.MOM.NatsNet.Server;

/// <summary>
/// Server configuration options block.
/// Mirrors <c>Options</c> struct in opts.go.
/// </summary>
public sealed partial class ServerOptions
{
    // -------------------------------------------------------------------------
    // General / Startup
    // -------------------------------------------------------------------------

    public string ConfigFile { get; set; } = string.Empty;
    [JsonPropertyName("server_name")]
    public string ServerName { get; set; } = string.Empty;
    [JsonPropertyName("host")]
    public string Host { get; set; } = string.Empty;
    [JsonPropertyName("port")]
    public int Port { get; set; }
    public bool DontListen { get; set; }
    [JsonPropertyName("client_advertise")]
    public string ClientAdvertise { get; set; } = string.Empty;
    public bool CheckConfig { get; set; }
    [JsonPropertyName("pid_file")]
    public string PidFile { get; set; } = string.Empty;
    [JsonPropertyName("ports_file_dir")]
    public string PortsFileDir { get; set; } = string.Empty;

    // -------------------------------------------------------------------------
    // Logging & Debugging
    // -------------------------------------------------------------------------

    [JsonPropertyName("trace")]
    public bool Trace { get; set; }
    [JsonPropertyName("debug")]
    public bool Debug { get; set; }
    public bool TraceVerbose { get; set; }
    public bool TraceHeaders { get; set; }
    public bool NoLog { get; set; }
    public bool NoSigs { get; set; }
    public bool Logtime { get; set; }
    public bool LogtimeUtc { get; set; }
    [JsonPropertyName("logfile")]
    public string LogFile { get; set; } = string.Empty;
    [JsonPropertyName("log_size_limit")]
    public long LogSizeLimit { get; set; }
    public long LogMaxFiles { get; set; }
    public bool Syslog { get; set; }
    public string RemoteSyslog { get; set; } = string.Empty;
    public int ProfPort { get; set; }
    public int ProfBlockRate { get; set; }
    public int MaxTracedMsgLen { get; set; }

    // -------------------------------------------------------------------------
    // Networking & Limits
    // -------------------------------------------------------------------------

    [JsonPropertyName("max_connections")]
    public int MaxConn { get; set; }
    public int MaxSubs { get; set; }
    public byte MaxSubTokens { get; set; }
    public int MaxControlLine { get; set; }
    [JsonPropertyName("max_payload")]
    public int MaxPayload { get; set; }
    [JsonPropertyName("max_pending")]
    public long MaxPending { get; set; }
    public bool NoFastProducerStall { get; set; }
    public bool ProxyRequired { get; set; }
    public bool ProxyProtocol { get; set; }
    public int MaxClosedClients { get; set; }

    // -------------------------------------------------------------------------
    // Connectivity
    // -------------------------------------------------------------------------

    [JsonPropertyName("ping_interval")]
    public TimeSpan PingInterval { get; set; }
    [JsonPropertyName("ping_max")]
    public int MaxPingsOut { get; set; }
    [JsonPropertyName("write_deadline")]
    public TimeSpan WriteDeadline { get; set; }
    public WriteTimeoutPolicy WriteTimeout { get; set; }
    [JsonPropertyName("lame_duck_duration")]
    public TimeSpan LameDuckDuration { get; set; }
    [JsonPropertyName("lame_duck_grace_period")]
    public TimeSpan LameDuckGracePeriod { get; set; }

    // -------------------------------------------------------------------------
    // HTTP / Monitoring
    // -------------------------------------------------------------------------

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

    // -------------------------------------------------------------------------
    // Authentication & Authorization
    // -------------------------------------------------------------------------

    [JsonPropertyName("username")]
    public string Username { get; set; } = string.Empty;
    [JsonPropertyName("password")]
    public string Password { get; set; } = string.Empty;
    [JsonPropertyName("authorization")]
    public string Authorization { get; set; } = string.Empty;
    [JsonPropertyName("auth_timeout")]
    public double AuthTimeout { get; set; }
    [JsonPropertyName("no_auth_user")]
    public string NoAuthUser { get; set; } = string.Empty;
    public string DefaultSentinel { get; set; } = string.Empty;
    [JsonPropertyName("system_account")]
    public string SystemAccount { get; set; } = string.Empty;
    public bool NoSystemAccount { get; set; }
    /// <summary>Parsed account objects from config. Mirrors Go opts.Accounts.</summary>
    [JsonPropertyName("accounts")]
    public List<Account> Accounts { get; set; } = [];
    public AuthCalloutOpts? AuthCallout { get; set; }
    public bool AlwaysEnableNonce { get; set; }
    public List<User>? Users { get; set; }
    public List<NkeyUser>? Nkeys { get; set; }
    public List<object> TrustedOperators { get; set; } = [];
    public IAuthentication? CustomClientAuthentication { get; set; }
    public IAuthentication? CustomRouterAuthentication { get; set; }

    // -------------------------------------------------------------------------
    // Sublist
    // -------------------------------------------------------------------------

    public bool NoSublistCache { get; set; }
    public bool NoHeaderSupport { get; set; }
    public bool DisableShortFirstPing { get; set; }

    // -------------------------------------------------------------------------
    // TLS (Client)
    // -------------------------------------------------------------------------

    public double TlsTimeout { get; set; }
    public bool Tls { get; set; }
    public bool TlsVerify { get; set; }
    public bool TlsMap { get; set; }
    public string TlsCert { get; set; } = string.Empty;
    public string TlsKey { get; set; } = string.Empty;
    public string TlsCaCert { get; set; } = string.Empty;
    public SslServerAuthenticationOptions? TlsConfig { get; set; }
    public PinnedCertSet? TlsPinnedCerts { get; set; }
    public long TlsRateLimit { get; set; }
    public bool TlsHandshakeFirst { get; set; }
    public TimeSpan TlsHandshakeFirstFallback { get; set; }
    public bool AllowNonTls { get; set; }

    // -------------------------------------------------------------------------
    // Cluster / Gateway / Leaf / WebSocket / MQTT
    // -------------------------------------------------------------------------

    [JsonPropertyName("cluster")]
    public ClusterOpts Cluster { get; set; } = new();
    [JsonPropertyName("gateway")]
    public GatewayOpts Gateway { get; set; } = new();
    [JsonPropertyName("leafnodes")]
    public LeafNodeOpts LeafNode { get; set; } = new();
    public WebsocketOpts Websocket { get; set; } = new();
    public MqttOpts Mqtt { get; set; } = new();

    // -------------------------------------------------------------------------
    // Routing
    // -------------------------------------------------------------------------

    public List<Uri> Routes { get; set; } = [];
    public string RoutesStr { get; set; } = string.Empty;

    // -------------------------------------------------------------------------
    // JetStream
    // -------------------------------------------------------------------------

    [JsonPropertyName("jetstream")]
    public bool JetStream { get; set; }
    public bool NoJetStreamStrict { get; set; }
    public long JetStreamMaxMemory { get; set; }
    public long JetStreamMaxStore { get; set; }
    public string JetStreamDomain { get; set; } = string.Empty;
    public string JetStreamExtHint { get; set; } = string.Empty;
    public string JetStreamKey { get; set; } = string.Empty;
    public string JetStreamOldKey { get; set; } = string.Empty;
    public StoreCipher JetStreamCipher { get; set; }
    public string JetStreamUniqueTag { get; set; } = string.Empty;
    public JsLimitOpts JetStreamLimits { get; set; } = new();
    public JsTpmOpts JetStreamTpm { get; set; } = new();
    public long JetStreamMaxCatchup { get; set; }
    public long JetStreamRequestQueueLimit { get; set; }
    public ulong JetStreamMetaCompact { get; set; }
    public ulong JetStreamMetaCompactSize { get; set; }
    public bool JetStreamMetaCompactSync { get; set; }
    public int StreamMaxBufferedMsgs { get; set; }
    public long StreamMaxBufferedSize { get; set; }
    [JsonPropertyName("store_dir")]
    public string StoreDir { get; set; } = string.Empty;
    public TimeSpan SyncInterval { get; set; }
    public bool SyncAlways { get; set; }
    public Dictionary<string, string> JsAccDefaultDomain { get; set; } = new();
    public bool DisableJetStreamBanner { get; set; }

    // -------------------------------------------------------------------------
    // Security & Trust
    // -------------------------------------------------------------------------

    public List<string> TrustedKeys { get; set; } = [];
    public SslServerAuthenticationOptions? AccountResolverTlsConfig { get; set; }
    public IAccountResolver? AccountResolver { get; set; }
    public OcspConfig? OcspConfig { get; set; }
    public OcspResponseCacheConfig? OcspCacheConfig { get; set; }

    // -------------------------------------------------------------------------
    // Tagging & Metadata
    // -------------------------------------------------------------------------

    public List<string> Tags { get; set; } = [];
    public Dictionary<string, string> Metadata { get; set; } = new();

    // -------------------------------------------------------------------------
    // Proxies
    // -------------------------------------------------------------------------

    public ProxiesConfig? Proxies { get; set; }

    // -------------------------------------------------------------------------
    // Connectivity error reporting
    // -------------------------------------------------------------------------

    public int ConnectErrorReports { get; set; }
    public int ReconnectErrorReports { get; set; }

    // -------------------------------------------------------------------------
    // Internal / Private fields
    // -------------------------------------------------------------------------

    internal Dictionary<string, bool> InConfig { get; set; } = new();
    internal Dictionary<string, bool> InCmdLine { get; set; } = new();
    internal List<string> OperatorJwt { get; set; } = [];
    internal Dictionary<string, string> ResolverPreloads { get; set; } = new();
    internal HashSet<string> ResolverPinnedAccounts { get; set; } = [];
    internal TimeSpan GatewaysSolicitDelay { get; set; }
    internal int OverrideProto { get; set; }
    internal bool MaxMemSet { get; set; }
    internal bool MaxStoreSet { get; set; }
    internal bool SyncSet { get; set; }
    internal bool AuthBlockDefined { get; set; }
    internal string ConfigDigestValue { get; set; } = string.Empty;
    internal TlsConfigOpts? TlsConfigOpts { get; set; }
}
