// 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.Runtime.InteropServices;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using ZB.MOM.NatsNet.Server.Auth;
using ZB.MOM.NatsNet.Server.Config;
using ZB.MOM.NatsNet.Server.Internal.DataStructures;

namespace ZB.MOM.NatsNet.Server;

// Global flag for unknown field handling.
internal static class ConfigFlags
{
    private static int _allowUnknownTopLevelField;

    /// <summary>
    /// Sets whether unknown top-level config fields should be allowed.
    /// Mirrors <c>NoErrOnUnknownFields</c> in opts.go.
    /// </summary>
    public static void NoErrOnUnknownFields(bool noError) =>
        Interlocked.Exchange(ref _allowUnknownTopLevelField, noError ? 1 : 0);

    public static bool AllowUnknownTopLevelField =>
        Interlocked.CompareExchange(ref _allowUnknownTopLevelField, 0, 0) != 0;
}

public sealed partial class ServerOptions
{
    /// <summary>
    /// Toggles unknown top-level field handling for config parsing.
    /// Mirrors <c>NoErrOnUnknownFields</c> in opts.go.
    /// </summary>
    public static void NoErrOnUnknownFields(bool noError) => ConfigFlags.NoErrOnUnknownFields(noError);

    /// <summary>
    /// Snapshot of command-line flags, populated during <see cref="ConfigureOptions"/>.
    /// Mirrors <c>FlagSnapshot</c> in opts.go.
    /// </summary>
    public static ServerOptions? FlagSnapshot { get; internal set; }

    /// <summary>
    /// Deep-copies this <see cref="ServerOptions"/> instance.
    /// Mirrors <c>Options.Clone()</c> in opts.go.
    /// </summary>
    public ServerOptions Clone()
    {
        // Start with a shallow memberwise clone.
        var clone = (ServerOptions)MemberwiseClone();

        // Deep-copy reference types that need isolation.
        if (Routes.Count > 0)
            clone.Routes = Routes.Select(u => new Uri(u.ToString())).ToList();

        clone.Cluster = CloneClusterOpts(Cluster);
        clone.Gateway = CloneGatewayOpts(Gateway);
        clone.LeafNode = CloneLeafNodeOpts(LeafNode);
        clone.Websocket = CloneWebsocketOpts(Websocket);
        clone.Mqtt = CloneMqttOpts(Mqtt);

        clone.Tags = [.. Tags];
        clone.Metadata = new Dictionary<string, string>(Metadata);
        clone.TrustedKeys = [.. TrustedKeys];
        clone.JsAccDefaultDomain = new Dictionary<string, string>(JsAccDefaultDomain);
        clone.InConfig = new Dictionary<string, bool>(InConfig);
        clone.InCmdLine = new Dictionary<string, bool>(InCmdLine);
        clone.OperatorJwt = [.. OperatorJwt];
        clone.ResolverPreloads = new Dictionary<string, string>(ResolverPreloads);
        clone.ResolverPinnedAccounts = [.. ResolverPinnedAccounts];

        return clone;
    }

    /// <summary>
    /// Returns the SHA-256 digest of the configuration.
    /// Mirrors <c>Options.ConfigDigest()</c> in opts.go.
    /// </summary>
    public string ConfigDigest() => ConfigDigestValue;

    // -------------------------------------------------------------------------
    // Merge / Baseline
    // -------------------------------------------------------------------------

    /// <summary>
    /// Merges file-based options with command-line flag options.
    /// Flag options override file options where set.
    /// Mirrors <c>MergeOptions</c> in opts.go.
    /// </summary>
    public static ServerOptions MergeOptions(ServerOptions? fileOpts, ServerOptions? flagOpts)
    {
        if (fileOpts == null) return flagOpts ?? new ServerOptions();
        if (flagOpts == null) return fileOpts;

        var opts = fileOpts.Clone();

        if (flagOpts.Port != 0) opts.Port = flagOpts.Port;
        if (!string.IsNullOrEmpty(flagOpts.Host)) opts.Host = flagOpts.Host;
        if (flagOpts.DontListen) opts.DontListen = true;
        if (!string.IsNullOrEmpty(flagOpts.ClientAdvertise)) opts.ClientAdvertise = flagOpts.ClientAdvertise;
        if (!string.IsNullOrEmpty(flagOpts.Username)) opts.Username = flagOpts.Username;
        if (!string.IsNullOrEmpty(flagOpts.Password)) opts.Password = flagOpts.Password;
        if (!string.IsNullOrEmpty(flagOpts.Authorization)) opts.Authorization = flagOpts.Authorization;
        if (flagOpts.HttpPort != 0) opts.HttpPort = flagOpts.HttpPort;
        if (!string.IsNullOrEmpty(flagOpts.HttpBasePath)) opts.HttpBasePath = flagOpts.HttpBasePath;
        if (flagOpts.Debug) opts.Debug = true;
        if (flagOpts.Trace) opts.Trace = true;
        if (flagOpts.Logtime) opts.Logtime = true;
        if (!string.IsNullOrEmpty(flagOpts.LogFile)) opts.LogFile = flagOpts.LogFile;
        if (!string.IsNullOrEmpty(flagOpts.PidFile)) opts.PidFile = flagOpts.PidFile;
        if (!string.IsNullOrEmpty(flagOpts.PortsFileDir)) opts.PortsFileDir = flagOpts.PortsFileDir;
        if (flagOpts.ProfPort != 0) opts.ProfPort = flagOpts.ProfPort;
        if (!string.IsNullOrEmpty(flagOpts.Cluster.ListenStr)) opts.Cluster.ListenStr = flagOpts.Cluster.ListenStr;
        if (flagOpts.Cluster.NoAdvertise) opts.Cluster.NoAdvertise = true;
        if (flagOpts.Cluster.ConnectRetries != 0) opts.Cluster.ConnectRetries = flagOpts.Cluster.ConnectRetries;
        if (!string.IsNullOrEmpty(flagOpts.Cluster.Advertise)) opts.Cluster.Advertise = flagOpts.Cluster.Advertise;
        if (!string.IsNullOrEmpty(flagOpts.RoutesStr)) MergeRoutes(opts, flagOpts);
        if (flagOpts.JetStream) opts.JetStream = true;
        if (!string.IsNullOrEmpty(flagOpts.StoreDir)) opts.StoreDir = flagOpts.StoreDir;

        return opts;
    }

    /// <summary>
    /// Parses route URLs from a comma-separated string.
    /// Mirrors <c>RoutesFromStr</c> in opts.go.
    /// </summary>
    public static List<Uri> RoutesFromStr(string routesStr)
    {
        var parts = routesStr.Split(',');
        if (parts.Length == 0) return [];

        var urls = new List<Uri>();
        foreach (var r in parts)
        {
            var trimmed = r.Trim();
            if (Uri.TryCreate(trimmed, UriKind.Absolute, out var u))
                urls.Add(u);
        }
        return urls;
    }

    /// <summary>
    /// Applies system-wide defaults to any unset options.
    /// Mirrors <c>setBaselineOptions</c> in opts.go.
    /// </summary>
    public void SetBaselineOptions()
    {
        if (string.IsNullOrEmpty(Host))
            Host = ServerConstants.DefaultHost;
        if (string.IsNullOrEmpty(HttpHost))
            HttpHost = Host;
        if (Port == 0)
            Port = ServerConstants.DefaultPort;
        else if (Port == ServerConstants.RandomPort)
            Port = 0;
        if (MaxConn == 0)
            MaxConn = ServerConstants.DefaultMaxConnections;
        if (PingInterval == TimeSpan.Zero)
            PingInterval = ServerConstants.DefaultPingInterval;
        if (MaxPingsOut == 0)
            MaxPingsOut = ServerConstants.DefaultPingMaxOut;
        if (TlsTimeout == 0)
            TlsTimeout = ServerConstants.TlsTimeout.TotalSeconds;
        if (AuthTimeout == 0)
            AuthTimeout = GetDefaultAuthTimeout(TlsConfig, TlsTimeout);

        // Cluster defaults
        if (Cluster.Port != 0 || !string.IsNullOrEmpty(Cluster.ListenStr))
        {
            if (string.IsNullOrEmpty(Cluster.Host))
                Cluster.Host = ServerConstants.DefaultHost;
            if (Cluster.TlsTimeout == 0)
                Cluster.TlsTimeout = ServerConstants.TlsTimeout.TotalSeconds;
            if (Cluster.AuthTimeout == 0)
                Cluster.AuthTimeout = GetDefaultAuthTimeout(Cluster.TlsConfig, Cluster.TlsTimeout);
            if (Cluster.PoolSize == 0)
                Cluster.PoolSize = ServerConstants.DefaultRoutePoolSize;

            // Add system account to pinned accounts if pool is enabled.
            if (Cluster.PoolSize > 0)
            {
                var sysAccName = SystemAccount;
                if (string.IsNullOrEmpty(sysAccName) && !NoSystemAccount)
                    sysAccName = ServerConstants.DefaultSystemAccount;
                if (!string.IsNullOrEmpty(sysAccName) && !Cluster.PinnedAccounts.Contains(sysAccName))
                    Cluster.PinnedAccounts.Add(sysAccName);
            }

            // Default compression to "accept".
            if (string.IsNullOrEmpty(Cluster.Compression.Mode))
                Cluster.Compression.Mode = CompressionModes.Accept;
        }

        // LeafNode defaults
        if (LeafNode.Port != 0)
        {
            if (string.IsNullOrEmpty(LeafNode.Host))
                LeafNode.Host = ServerConstants.DefaultHost;
            if (LeafNode.TlsTimeout == 0)
                LeafNode.TlsTimeout = ServerConstants.TlsTimeout.TotalSeconds;
            if (LeafNode.AuthTimeout == 0)
                LeafNode.AuthTimeout = GetDefaultAuthTimeout(LeafNode.TlsConfig, LeafNode.TlsTimeout);
            if (string.IsNullOrEmpty(LeafNode.Compression.Mode))
                LeafNode.Compression.Mode = CompressionModes.S2Auto;
        }

        // Remote leafnode defaults
        foreach (var r in LeafNode.Remotes)
        {
            foreach (var u in r.Urls)
            {
                if (u.IsDefaultPort || string.IsNullOrEmpty(u.GetComponents(UriComponents.Port, UriFormat.Unescaped)))
                {
                    var builder = new UriBuilder(u) { Port = ServerConstants.DefaultLeafNodePort };
                    r.Urls[r.Urls.IndexOf(u)] = builder.Uri;
                }
            }
            if (string.IsNullOrEmpty(r.Compression.Mode))
                r.Compression.Mode = CompressionModes.S2Auto;
            if (r.FirstInfoTimeout <= TimeSpan.Zero)
                r.FirstInfoTimeout = ServerConstants.DefaultLeafNodeInfoWait;
        }

        if (LeafNode.ReconnectInterval == TimeSpan.Zero)
            LeafNode.ReconnectInterval = ServerConstants.DefaultLeafNodeReconnect;

        // Protocol limits
        if (MaxControlLine == 0)
            MaxControlLine = ServerConstants.MaxControlLineSize;
        if (MaxPayload == 0)
            MaxPayload = ServerConstants.MaxPayloadSize;
        if (MaxPending == 0)
            MaxPending = ServerConstants.MaxPendingSize;
        if (WriteDeadline == TimeSpan.Zero)
            WriteDeadline = ServerConstants.DefaultFlushDeadline;
        if (MaxClosedClients == 0)
            MaxClosedClients = ServerConstants.DefaultMaxClosedClients;
        if (LameDuckDuration == TimeSpan.Zero)
            LameDuckDuration = ServerConstants.DefaultLameDuckDuration;
        if (LameDuckGracePeriod == TimeSpan.Zero)
            LameDuckGracePeriod = ServerConstants.DefaultLameDuckGracePeriod;

        // Gateway defaults
        if (Gateway.Port != 0)
        {
            if (string.IsNullOrEmpty(Gateway.Host))
                Gateway.Host = ServerConstants.DefaultHost;
            if (Gateway.TlsTimeout == 0)
                Gateway.TlsTimeout = ServerConstants.TlsTimeout.TotalSeconds;
            if (Gateway.AuthTimeout == 0)
                Gateway.AuthTimeout = GetDefaultAuthTimeout(Gateway.TlsConfig, Gateway.TlsTimeout);
        }

        // Error reporting
        if (ConnectErrorReports == 0)
            ConnectErrorReports = ServerConstants.DefaultConnectErrorReports;
        if (ReconnectErrorReports == 0)
            ReconnectErrorReports = ServerConstants.DefaultReconnectErrorReports;

        // WebSocket defaults
        if (Websocket.Port != 0)
        {
            if (string.IsNullOrEmpty(Websocket.Host))
                Websocket.Host = ServerConstants.DefaultHost;
        }

        // MQTT defaults
        if (Mqtt.Port != 0)
        {
            if (string.IsNullOrEmpty(Mqtt.Host))
                Mqtt.Host = ServerConstants.DefaultHost;
            if (Mqtt.TlsTimeout == 0)
                Mqtt.TlsTimeout = ServerConstants.TlsTimeout.TotalSeconds;
        }

        // JetStream defaults
        if (JetStreamMaxMemory == 0 && !MaxMemSet)
            JetStreamMaxMemory = -1;
        if (JetStreamMaxStore == 0 && !MaxStoreSet)
            JetStreamMaxStore = -1;
        if (SyncInterval == TimeSpan.Zero && !SyncSet)
            SyncInterval = TimeSpan.FromMinutes(2); // defaultSyncInterval
        if (JetStreamRequestQueueLimit <= 0)
            JetStreamRequestQueueLimit = 4096; // JSDefaultRequestQueueLimit
    }

    /// <summary>
    /// Normalizes an HTTP base path (ensure leading slash, clean redundant separators).
    /// Mirrors <c>normalizeBasePath</c> in opts.go.
    /// </summary>
    public static string NormalizeBasePath(string p)
    {
        if (string.IsNullOrEmpty(p)) return "/";
        if (p[0] != '/') p = "/" + p;
        // Simple path clean: collapse repeated slashes and remove trailing slash.
        while (p.Contains("//")) p = p.Replace("//", "/");
        return p.Length > 1 && p.EndsWith('/') ? p[..^1] : p;
    }

    /// <summary>
    /// Computes the default auth timeout based on TLS config presence.
    /// Mirrors <c>getDefaultAuthTimeout</c> in opts.go.
    /// </summary>
    public static double GetDefaultAuthTimeout(object? tlsConfig, double tlsTimeout)
    {
        if (tlsConfig != null)
            return tlsTimeout + 1.0;
        return ServerConstants.AuthTimeout.TotalSeconds;
    }

    /// <summary>
    /// Returns the user's home directory.
    /// Mirrors <c>homeDir</c> in opts.go.
    /// </summary>
    public static string HomeDir() => Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

    /// <summary>
    /// Expands environment variables and ~/ prefix in a path.
    /// Mirrors <c>expandPath</c> in opts.go.
    /// </summary>
    public static string ExpandPath(string p)
    {
        p = Environment.ExpandEnvironmentVariables(p);
        if (!p.StartsWith('~')) return p;
        return Path.Combine(HomeDir(), p[1..].TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
    }

    /// <summary>
    /// Reads a PID from a file path if possible, otherwise returns the string as-is.
    /// Mirrors <c>maybeReadPidFile</c> in opts.go.
    /// </summary>
    public static string MaybeReadPidFile(string pidStr)
    {
        try { return File.ReadAllText(pidStr).Trim(); }
        catch { return pidStr; }
    }

    /// <summary>
    /// Applies TLS overrides from command-line options.
    /// Mirrors <c>overrideTLS</c> in opts.go.
    /// </summary>
    public Exception? OverrideTls()
    {
        if (string.IsNullOrEmpty(TlsCert))
            return new InvalidOperationException("TLS Server certificate must be present and valid");
        if (string.IsNullOrEmpty(TlsKey))
            return new InvalidOperationException("TLS Server private key must be present and valid");

        // TLS config generation is deferred to GenTlsConfig (session 06+).
        // For now, mark that TLS is enabled.
        Tls = true;
        return null;
    }

    /// <summary>
    /// Overrides cluster options from the --cluster flag.
    /// Mirrors <c>overrideCluster</c> in opts.go.
    /// </summary>
    public Exception? OverrideCluster()
    {
        if (string.IsNullOrEmpty(Cluster.ListenStr))
        {
            Cluster.Port = 0;
            return null;
        }

        var listenStr = Cluster.ListenStr;
        var wantsRandom = false;
        if (listenStr.EndsWith(":-1"))
        {
            wantsRandom = true;
            listenStr = listenStr[..^3] + ":0";
        }

        if (!Uri.TryCreate(listenStr, UriKind.Absolute, out var clusterUri))
            return new InvalidOperationException($"could not parse cluster URL: {Cluster.ListenStr}");

        Cluster.Host = clusterUri.Host;
        Cluster.Port = wantsRandom ? -1 : clusterUri.Port;

        var userInfo = clusterUri.UserInfo;
        if (!string.IsNullOrEmpty(userInfo))
        {
            var parts = userInfo.Split(':', 2);
            if (parts.Length != 2)
                return new InvalidOperationException("expected cluster password to be set");
            Cluster.Username = parts[0];
            Cluster.Password = parts[1];
        }
        else
        {
            Cluster.Username = string.Empty;
            Cluster.Password = string.Empty;
        }

        return null;
    }

    // -------------------------------------------------------------------------
    // Batch 6: opts.go package-level parse/config helpers (F1)
    // -------------------------------------------------------------------------

    /// <summary>
    /// Deep copies route/gateway URL lists.
    /// Mirrors <c>deepCopyURLs</c> in opts.go.
    /// </summary>
    public static List<Uri>? DeepCopyURLs(IReadOnlyList<Uri>? urls)
    {
        if (urls == null)
            return null;

        var copied = new List<Uri>(urls.Count);
        foreach (var u in urls)
            copied.Add(new Uri(u.ToString(), UriKind.Absolute));
        return copied;
    }

    /// <summary>
    /// Loads server options from a config file.
    /// Mirrors package-level <c>ProcessConfigFile</c> in opts.go.
    /// </summary>
    public static ServerOptions ProcessConfigFile(string configFile) =>
        ServerOptionsConfiguration.ProcessConfigFile(configFile);

    /// <summary>
    /// Receiver-style config loader that updates this instance with values from
    /// <paramref name="configFile"/>.
    /// Mirrors Go <c>Options.ProcessConfigFile</c>.
    /// </summary>
    public Exception? ProcessConfigFileOverload2510(string configFile)
    {
        ConfigFile = configFile;
        if (string.IsNullOrEmpty(configFile))
            return null;

        try
        {
            var data = File.ReadAllText(configFile);
            ConfigDigestValue = ComputeConfigDigest(data);
            return ProcessConfigString(data);
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

    /// <summary>
    /// Receiver-style config loader from in-memory content.
    /// Mirrors Go <c>Options.ProcessConfigString</c>.
    /// </summary>
    public Exception? ProcessConfigString(string data)
    {
        try
        {
            using var doc = JsonDocument.Parse(
                data,
                new JsonDocumentOptions
                {
                    AllowTrailingCommas = true,
                    CommentHandling = JsonCommentHandling.Skip,
                });

            if (doc.RootElement.ValueKind != JsonValueKind.Object)
                return new InvalidOperationException("configuration root must be an object");

            var normalized = NormalizeConfigValue(doc.RootElement);
            var configMap = normalized as IReadOnlyDictionary<string, object?>
                ?? normalized as Dictionary<string, object?>;
            if (configMap == null)
                return new InvalidOperationException("configuration root must be a key/value object");

            return ProcessConfigFileInternal(string.Empty, configMap);
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

    /// <summary>
    /// Internal receiver config pipeline that processes each top-level config key.
    /// Mirrors Go <c>Options.processConfigFile</c>.
    /// </summary>
    public Exception? ProcessConfigFileInternal(string configFile, IReadOnlyDictionary<string, object?> config)
    {
        var errors = new List<Exception>();
        var warnings = new List<Exception>();

        if (config.Count == 0)
            warnings.Add(new InvalidOperationException($"{configFile}: config has no values or is empty"));

        var sysErr = ConfigureSystemAccount(this, config);
        if (sysErr != null)
            errors.Add(sysErr);

        foreach (var (key, value) in config)
            ProcessConfigFileLine(key, value, errors, warnings);

        if (AuthCallout?.AllowedAccounts is { Count: > 0 })
        {
            var configuredAccounts = new HashSet<string>(
                Accounts.Select(a => a.Name),
                StringComparer.Ordinal);

            foreach (var account in AuthCallout.AllowedAccounts)
            {
                if (!configuredAccounts.Contains(account))
                {
                    errors.Add(new InvalidOperationException(
                        $"auth_callout allowed account \"{account}\" not found in configured accounts"));
                }
            }
        }

        if (errors.Count == 0 && warnings.Count == 0)
            return null;

        return new ProcessConfigException(errors, warnings);
    }

    /// <summary>
    /// Processes a single top-level config key.
    /// Mirrors Go <c>Options.processConfigFileLine</c>.
    /// </summary>
    public void ProcessConfigFileLine(
        string key,
        object? value,
        ICollection<Exception> errors,
        ICollection<Exception> warnings)
    {
        try
        {
            var normalized = NormalizeConfigValue(value);
            switch (key.ToLowerInvariant())
            {
                case "listen":
                    {
                        var (host, port) = ParseListen(normalized);
                        Host = host;
                        Port = port;
                        break;
                    }
                case "client_advertise":
                    if (normalized is string ca)
                        ClientAdvertise = ca;
                    else
                        errors.Add(new InvalidOperationException("client_advertise must be a string"));
                    break;
                case "port":
                    if (TryConvertToLong(normalized, out var p))
                        Port = checked((int)p);
                    else
                        errors.Add(new InvalidOperationException("port must be an integer"));
                    break;
                case "server_name":
                    if (normalized is not string sn)
                    {
                        errors.Add(new InvalidOperationException("server_name must be a string"));
                    }
                    else if (sn.Contains(' '))
                    {
                        errors.Add(ServerErrors.ErrServerNameHasSpaces);
                    }
                    else
                    {
                        ServerName = sn;
                    }
                    break;
                case "host":
                case "net":
                    if (normalized is string configuredHost)
                        Host = configuredHost;
                    else
                        errors.Add(new InvalidOperationException($"{key} must be a string"));
                    break;
                case "debug":
                    if (TryConvertToBool(normalized, out var debug))
                    {
                        Debug = debug;
                        TrackExplicitVal(InConfig, nameof(Debug), Debug);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("debug must be a boolean"));
                    }
                    break;
                case "trace":
                    if (TryConvertToBool(normalized, out var trace))
                    {
                        Trace = trace;
                        TrackExplicitVal(InConfig, nameof(Trace), Trace);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("trace must be a boolean"));
                    }
                    break;
                case "trace_verbose":
                    if (TryConvertToBool(normalized, out var traceVerbose))
                    {
                        TraceVerbose = traceVerbose;
                        Trace = traceVerbose;
                        TrackExplicitVal(InConfig, nameof(TraceVerbose), TraceVerbose);
                        TrackExplicitVal(InConfig, nameof(Trace), Trace);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("trace_verbose must be a boolean"));
                    }
                    break;
                case "trace_headers":
                    if (TryConvertToBool(normalized, out var traceHeaders))
                    {
                        TraceHeaders = traceHeaders;
                        Trace = traceHeaders;
                        TrackExplicitVal(InConfig, nameof(TraceHeaders), TraceHeaders);
                        TrackExplicitVal(InConfig, nameof(Trace), Trace);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("trace_headers must be a boolean"));
                    }
                    break;
                case "logtime":
                    if (TryConvertToBool(normalized, out var logtime))
                    {
                        Logtime = logtime;
                        TrackExplicitVal(InConfig, nameof(Logtime), Logtime);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("logtime must be a boolean"));
                    }
                    break;
                case "logtime_utc":
                    if (TryConvertToBool(normalized, out var logtimeUtc))
                    {
                        LogtimeUtc = logtimeUtc;
                        TrackExplicitVal(InConfig, nameof(LogtimeUtc), LogtimeUtc);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("logtime_utc must be a boolean"));
                    }
                    break;
                case "disable_sublist_cache":
                case "no_sublist_cache":
                    if (TryConvertToBool(normalized, out var noSublistCache))
                        NoSublistCache = noSublistCache;
                    else
                        errors.Add(new InvalidOperationException($"{key} must be a boolean"));
                    break;
                case "accounts":
                    {
                        var err = ParseAccounts(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "default_sentinel":
                    if (normalized is string sentinel)
                        DefaultSentinel = sentinel;
                    else
                        errors.Add(new InvalidOperationException("default_sentinel must be a string"));
                    break;
                case "authorization":
                    {
                        var (auth, err) = ParseAuthorization(normalized, errors, warnings);
                        if (err != null)
                        {
                            errors.Add(err);
                            break;
                        }

                        if (auth == null)
                            break;

                        AuthBlockDefined = true;
                        Username = auth.User;
                        Password = auth.Pass;
                        ProxyRequired = auth.ProxyRequired;
                        Authorization = auth.Token;
                        AuthTimeout = auth.TimeoutSeconds;
                        AuthCallout = auth.Callout;

                        if ((!string.IsNullOrEmpty(auth.User) || !string.IsNullOrEmpty(auth.Pass)) &&
                            !string.IsNullOrEmpty(auth.Token))
                        {
                            errors.Add(new InvalidOperationException("Cannot have a user/pass and token"));
                        }
                        break;
                    }
                case "cluster":
                    {
                        var err = ParseCluster(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "gateway":
                    {
                        var err = ParseGateway(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "leafnodes":
                    {
                        var err = ParseLeafNodes(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "routes":
                    if (normalized is string routesString)
                    {
                        RoutesStr = routesString;
                        Routes = RoutesFromStr(routesString);
                        break;
                    }

                    if (TryGetArray(normalized, out var routes))
                    {
                        Routes = ParseURLs(routes, "route", warnings, errors);
                    }
                    else
                    {
                        errors.Add(new InvalidOperationException("routes must be a string or array"));
                    }
                    break;
                case "jetstream":
                    {
                        var err = ParseJetStream(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "websocket":
                    {
                        var err = ParseWebsocket(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "mqtt":
                    {
                        var err = ParseMQTT(normalized, this, errors, warnings);
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                case "proxies":
                    {
                        var (proxies, err) = ParseProxies(normalized);
                        if (err != null)
                            errors.Add(err);
                        else
                            Proxies = proxies;
                        break;
                    }
                case "system_account":
                case "system":
                    {
                        var err = ConfigureSystemAccount(
                            this,
                            new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
                            {
                                [key] = normalized,
                            });
                        if (err != null)
                            errors.Add(err);
                        break;
                    }
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors.Add(new InvalidOperationException($"unknown field \"{key}\""));
                    break;
            }
        }
        catch (Exception ex)
        {
            errors.Add(ex);
        }
    }

    /// <summary>
    /// Normalizes token-like values to plain CLR values.
    /// Mirrors <c>unwrapValue</c> intent from opts.go.
    /// </summary>
    public static object? UnwrapValue(object? value) => NormalizeConfigValue(value);

    /// <summary>
    /// Converts a recovered panic/exception to an error list entry.
    /// Mirrors <c>convertPanicToErrorList</c> in opts.go.
    /// </summary>
    public static void ConvertPanicToErrorList(Exception? panic, ICollection<Exception>? errors, string? context = null)
    {
        if (panic == null || errors == null)
            return;

        var message = string.IsNullOrWhiteSpace(context)
            ? "encountered panic while processing config"
            : $"encountered panic while processing {context}";
        errors.Add(new InvalidOperationException(message, panic));
    }

    /// <summary>
    /// Converts a recovered panic/exception to a single error output.
    /// Mirrors <c>convertPanicToError</c> in opts.go.
    /// </summary>
    public static void ConvertPanicToError(Exception? panic, ref Exception? error, string? context = null)
    {
        if (panic == null || error != null)
            return;

        var message = string.IsNullOrWhiteSpace(context)
            ? "encountered panic while processing config"
            : $"encountered panic while processing {context}";
        error = new InvalidOperationException(message, panic);
    }

    /// <summary>
    /// Applies <c>system_account</c>/<c>system</c> config values.
    /// Mirrors <c>configureSystemAccount</c> in opts.go.
    /// </summary>
    public static Exception? ConfigureSystemAccount(ServerOptions options, IReadOnlyDictionary<string, object?> config)
    {
        ArgumentNullException.ThrowIfNull(options);
        ArgumentNullException.ThrowIfNull(config);

        if (!TryGetFirst(config, ["system_account", "system"], out var value))
            return null;

        if (value is not string systemAccount)
            return new InvalidOperationException("system account name must be a string");

        options.SystemAccount = systemAccount;
        return null;
    }

    /// <summary>
    /// Builds a username/nkey identity map for duplicate detection.
    /// Mirrors <c>setupUsersAndNKeysDuplicateCheckMap</c> in opts.go.
    /// </summary>
    public static HashSet<string> SetupUsersAndNKeysDuplicateCheckMap(ServerOptions options)
    {
        ArgumentNullException.ThrowIfNull(options);

        var identities = new HashSet<string>(StringComparer.Ordinal);
        if (options.Users != null)
        {
            foreach (var user in options.Users)
            {
                if (!string.IsNullOrWhiteSpace(user.Username))
                    identities.Add(user.Username);
            }
        }

        if (options.Nkeys != null)
        {
            foreach (var user in options.Nkeys)
            {
                if (!string.IsNullOrWhiteSpace(user.Nkey))
                    identities.Add(user.Nkey);
            }
        }

        return identities;
    }

    /// <summary>
    /// Parses a duration from config value.
    /// Mirrors <c>parseDuration</c> in opts.go.
    /// </summary>
    public static TimeSpan ParseDuration(
        string field,
        object? value,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        if (value is string s)
        {
            try
            {
                return NatsDurationJsonConverter.Parse(s);
            }
            catch (Exception ex)
            {
                errors?.Add(new InvalidOperationException($"error parsing {field}: {ex.Message}", ex));
                return TimeSpan.Zero;
            }
        }

        if (TryConvertToLong(value, out var legacySeconds))
        {
            warnings?.Add(new InvalidOperationException($"{field} should be converted to a duration"));
            return TimeSpan.FromSeconds(legacySeconds);
        }

        errors?.Add(new InvalidOperationException($"{field} should be a duration string or number of seconds"));
        return TimeSpan.Zero;
    }

    /// <summary>
    /// Parses write timeout policy value.
    /// Mirrors <c>parseWriteDeadlinePolicy</c> in opts.go.
    /// </summary>
    public static WriteTimeoutPolicy ParseWriteDeadlinePolicy(string value, ICollection<Exception>? errors = null) =>
        value.ToLowerInvariant() switch
        {
            "default" => WriteTimeoutPolicy.Default,
            "close" => WriteTimeoutPolicy.Close,
            "retry" => WriteTimeoutPolicy.Retry,
            _ => ParseWriteDeadlinePolicyFallback(value, errors),
        };

    /// <summary>
    /// Parses <c>listen</c> values (<c>port</c> or <c>host:port</c>).
    /// Mirrors <c>parseListen</c> in opts.go.
    /// </summary>
    public static (string Host, int Port) ParseListen(object? value)
    {
        if (TryConvertToLong(value, out var portOnly))
            return (string.Empty, checked((int)portOnly));

        if (value is not string address)
            throw new InvalidOperationException($"expected port or host:port, got {value?.GetType().Name ?? "null"}");

        if (!TrySplitHostPort(address, out var host, out var port))
            throw new InvalidOperationException($"could not parse address string \"{address}\"");

        return (host, port);
    }

    /// <summary>
    /// Parses cluster block config.
    /// Mirrors <c>parseCluster</c> in opts.go.
    /// </summary>
    public static Exception? ParseCluster(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var clusterMap))
            return new InvalidOperationException($"Expected map to define cluster, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in clusterMap)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);

            switch (key)
            {
                case "name":
                {
                    var name = entry as string ?? string.Empty;
                    if (name.Contains(' '))
                    {
                        errors?.Add(new InvalidOperationException(ServerErrors.ErrClusterNameHasSpaces.Message));
                        break;
                    }

                    options.Cluster.Name = name;
                    break;
                }
                case "listen":
                {
                    try
                    {
                        var (host, port) = ParseListen(entry);
                        options.Cluster.Host = host;
                        options.Cluster.Port = port;
                    }
                    catch (Exception ex)
                    {
                        errors?.Add(ex);
                    }

                    break;
                }
                case "port":
                    if (TryConvertToLong(entry, out var clusterPort))
                        options.Cluster.Port = checked((int)clusterPort);
                    break;
                case "host":
                case "net":
                    options.Cluster.Host = entry as string ?? string.Empty;
                    break;
                case "authorization":
                {
                    var auth = ParseSimpleAuthorization(entry, errors, warnings);
                    if (auth == null)
                        break;
                    if (auth.HasUsers)
                    {
                        errors?.Add(new InvalidOperationException("Cluster authorization does not allow multiple users"));
                        break;
                    }

                    if (!string.IsNullOrEmpty(auth.Token))
                    {
                        errors?.Add(new InvalidOperationException("Cluster authorization does not support tokens"));
                        break;
                    }

                    if (auth.HasCallout)
                    {
                        errors?.Add(new InvalidOperationException("Cluster authorization does not support callouts"));
                        break;
                    }

                    options.Cluster.Username = auth.Username;
                    options.Cluster.Password = auth.Password;
                    if (auth.TimeoutSeconds > 0)
                        options.Cluster.AuthTimeout = auth.TimeoutSeconds;
                    break;
                }
                case "routes":
                    if (TryGetArray(entry, out var routes))
                        options.Routes = ParseURLs(routes, "route", warnings, errors);
                    break;
                case "cluster_advertise":
                case "advertise":
                    options.Cluster.Advertise = entry as string ?? string.Empty;
                    break;
                case "no_advertise":
                    if (TryConvertToBool(entry, out var noAdvertise))
                    {
                        options.Cluster.NoAdvertise = noAdvertise;
                        TrackExplicitVal(options.InConfig, "Cluster.NoAdvertise", noAdvertise);
                    }

                    break;
                case "connect_retries":
                    if (TryConvertToLong(entry, out var retries))
                        options.Cluster.ConnectRetries = checked((int)retries);
                    break;
                case "connect_backoff":
                    if (TryConvertToBool(entry, out var connectBackoff))
                        options.Cluster.ConnectBackoff = connectBackoff;
                    break;
                case "compression":
                {
                    var parseError = ParseCompression(
                        options.Cluster.Compression,
                        CompressionModes.S2Fast,
                        "compression",
                        entry);
                    if (parseError != null)
                        errors?.Add(parseError);
                    break;
                }
                case "ping_interval":
                    options.Cluster.PingInterval = ParseDuration("ping_interval", entry, errors, warnings);
                    break;
                case "ping_max":
                    if (TryConvertToLong(entry, out var pingMax))
                        options.Cluster.MaxPingsOut = checked((int)pingMax);
                    break;
                case "write_deadline":
                    options.Cluster.WriteDeadline = ParseDuration("write_deadline", entry, errors, warnings);
                    break;
                case "write_timeout":
                    options.Cluster.WriteTimeout = ParseWriteDeadlinePolicy(entry as string ?? string.Empty, errors);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses compression option values from bool/string/map forms.
    /// Mirrors <c>parseCompression</c> in opts.go.
    /// </summary>
    public static Exception? ParseCompression(
        CompressionOpts compression,
        string chosenModeForOn,
        string fieldName,
        object? value)
    {
        ArgumentNullException.ThrowIfNull(compression);

        switch (NormalizeConfigValue(value))
        {
            case string mode:
                compression.Mode = mode;
                return null;
            case bool enabled:
                compression.Mode = enabled ? chosenModeForOn : CompressionModes.Off;
                return null;
            default:
                if (!TryGetMap(value, out var map))
                    return new InvalidOperationException(
                        $"field \"{fieldName}\" should be a boolean or a structure, got {value?.GetType().Name ?? "null"}");

                foreach (var (rawKey, rawValue) in map)
                {
                    var key = rawKey.ToLowerInvariant();
                    var entry = NormalizeConfigValue(rawValue);
                    switch (key)
                    {
                        case "mode":
                            compression.Mode = entry as string ?? string.Empty;
                            break;
                        case "rtt_thresholds":
                        case "thresholds":
                        case "rtts":
                        case "rtt":
                            if (!TryGetArray(entry, out var thresholds))
                                return new InvalidOperationException("rtt_thresholds should be an array");

                            foreach (var threshold in thresholds)
                            {
                                if (threshold is not string thresholdValue)
                                    return new InvalidOperationException("rtt_thresholds entries should be duration strings");
                                compression.RttThresholds.Add(NatsDurationJsonConverter.Parse(thresholdValue));
                            }

                            break;
                        default:
                            return new InvalidOperationException($"unknown field \"{rawKey}\"");
                    }
                }

                return null;
        }
    }

    /// <summary>
    /// Parses URL arrays with duplicate detection.
    /// Mirrors <c>parseURLs</c> in opts.go.
    /// </summary>
    public static List<Uri> ParseURLs(
        IEnumerable<object?> values,
        string type,
        ICollection<Exception>? warnings = null,
        ICollection<Exception>? errors = null)
    {
        var urls = new List<Uri>();
        var dedupe = new HashSet<string>(StringComparer.Ordinal);
        foreach (var rawValue in values)
        {
            if (NormalizeConfigValue(rawValue) is not string urlValue)
            {
                errors?.Add(new InvalidOperationException($"{type} url must be a string"));
                continue;
            }

            if (!dedupe.Add(urlValue))
            {
                warnings?.Add(new InvalidOperationException($"Duplicate {type} entry detected: {urlValue}"));
                continue;
            }

            try
            {
                urls.Add(ParseURL(urlValue, type));
            }
            catch (Exception ex)
            {
                errors?.Add(ex);
            }
        }

        return urls;
    }

    /// <summary>
    /// Parses a single URL entry.
    /// Mirrors <c>parseURL</c> in opts.go.
    /// </summary>
    public static Uri ParseURL(string value, string type)
    {
        var trimmed = value.Trim();
        if (!Uri.TryCreate(trimmed, UriKind.Absolute, out var parsed))
            throw new InvalidOperationException($"error parsing {type} url [\"{trimmed}\"]");
        return parsed;
    }

    /// <summary>
    /// Parses gateway block config.
    /// Mirrors <c>parseGateway</c> in opts.go.
    /// </summary>
    public static Exception? ParseGateway(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var gatewayMap))
            return new InvalidOperationException($"Expected gateway to be a map, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in gatewayMap)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);

            switch (key)
            {
                case "name":
                {
                    var name = entry as string ?? string.Empty;
                    if (name.Contains(' '))
                    {
                        errors?.Add(new InvalidOperationException(ServerErrors.ErrGatewayNameHasSpaces.Message));
                        break;
                    }

                    options.Gateway.Name = name;
                    break;
                }
                case "listen":
                {
                    try
                    {
                        var (host, port) = ParseListen(entry);
                        options.Gateway.Host = host;
                        options.Gateway.Port = port;
                    }
                    catch (Exception ex)
                    {
                        errors?.Add(ex);
                    }

                    break;
                }
                case "port":
                    if (TryConvertToLong(entry, out var gatewayPort))
                        options.Gateway.Port = checked((int)gatewayPort);
                    break;
                case "host":
                case "net":
                    options.Gateway.Host = entry as string ?? string.Empty;
                    break;
                case "authorization":
                {
                    var auth = ParseSimpleAuthorization(entry, errors, warnings);
                    if (auth == null)
                        break;
                    if (auth.HasUsers)
                    {
                        errors?.Add(new InvalidOperationException("Gateway authorization does not allow multiple users"));
                        break;
                    }

                    if (!string.IsNullOrEmpty(auth.Token))
                    {
                        errors?.Add(new InvalidOperationException("Gateway authorization does not support tokens"));
                        break;
                    }

                    if (auth.HasCallout)
                    {
                        errors?.Add(new InvalidOperationException("Gateway authorization does not support callouts"));
                        break;
                    }

                    options.Gateway.Username = auth.Username;
                    options.Gateway.Password = auth.Password;
                    if (auth.TimeoutSeconds > 0)
                        options.Gateway.AuthTimeout = auth.TimeoutSeconds;
                    break;
                }
                case "advertise":
                    options.Gateway.Advertise = entry as string ?? string.Empty;
                    break;
                case "connect_retries":
                    if (TryConvertToLong(entry, out var retries))
                        options.Gateway.ConnectRetries = checked((int)retries);
                    break;
                case "connect_backoff":
                    if (TryConvertToBool(entry, out var connectBackoff))
                        options.Gateway.ConnectBackoff = connectBackoff;
                    break;
                case "reject_unknown":
                case "reject_unknown_cluster":
                    if (TryConvertToBool(entry, out var rejectUnknown))
                        options.Gateway.RejectUnknown = rejectUnknown;
                    break;
                case "write_deadline":
                    options.Gateway.WriteDeadline = ParseDuration("write_deadline", entry, errors, warnings);
                    break;
                case "write_timeout":
                    options.Gateway.WriteTimeout = ParseWriteDeadlinePolicy(entry as string ?? string.Empty, errors);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    // -------------------------------------------------------------------------
    // Batch 6: opts.go package-level parse/config helpers (F2)
    // -------------------------------------------------------------------------

    /// <summary>
    /// Parses JetStream account enablement/limits for an account-level block.
    /// Mirrors <c>parseJetStreamForAccount</c> in opts.go.
    /// </summary>
    public static Exception? ParseJetStreamForAccount(
        object? value,
        Account account,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(account);

        var normalized = NormalizeConfigValue(value);
        switch (normalized)
        {
            case bool enabled:
                account.JetStreamLimits = enabled ? CreateDefaultJetStreamAccountTiers() : null;
                return null;
            case string mode:
                switch (mode.Trim().ToLowerInvariant())
                {
                    case "enabled":
                    case "enable":
                        account.JetStreamLimits = CreateDefaultJetStreamAccountTiers();
                        return null;
                    case "disabled":
                    case "disable":
                        account.JetStreamLimits = null;
                        return null;
                    default:
                        return new InvalidOperationException(
                            $"Expected 'enabled' or 'disabled' for string value, got '{mode}'");
                }
            default:
                if (!TryGetMap(normalized, out var map))
                {
                    return new InvalidOperationException(
                        $"Expected map, bool or string to define JetStream, got {normalized?.GetType().Name ?? "null"}");
                }

                var limits = CreateUnlimitedJetStreamAccountLimits();
                foreach (var (rawKey, rawValue) in map)
                {
                    var key = rawKey.ToLowerInvariant();
                    var entry = NormalizeConfigValue(rawValue);
                    switch (key)
                    {
                        case "max_memory":
                        case "max_mem":
                        case "mem":
                        case "memory":
                            if (!TryConvertToLong(entry, out var maxMemory))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.MaxMemory = maxMemory;
                            break;
                        case "max_store":
                        case "max_file":
                        case "max_disk":
                        case "store":
                        case "disk":
                            if (!TryConvertToLong(entry, out var maxStore))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.MaxStore = maxStore;
                            break;
                        case "max_streams":
                        case "streams":
                            if (!TryConvertToLong(entry, out var maxStreams))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.MaxStreams = checked((int)maxStreams);
                            break;
                        case "max_consumers":
                        case "consumers":
                            if (!TryConvertToLong(entry, out var maxConsumers))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.MaxConsumers = checked((int)maxConsumers);
                            break;
                        case "max_bytes_required":
                        case "max_stream_bytes":
                        case "max_bytes":
                            if (!TryConvertToBool(entry, out var maxBytesRequired))
                                return new InvalidOperationException($"Expected a parseable bool for \"{rawKey}\", got {entry}");
                            limits.MaxBytesRequired = maxBytesRequired;
                            break;
                        case "mem_max_stream_bytes":
                        case "memory_max_stream_bytes":
                            if (!TryConvertToLong(entry, out var memoryMaxStreamBytes))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.MemoryMaxStreamBytes = memoryMaxStreamBytes;
                            break;
                        case "disk_max_stream_bytes":
                        case "store_max_stream_bytes":
                            if (!TryConvertToLong(entry, out var storeMaxStreamBytes))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.StoreMaxStreamBytes = storeMaxStreamBytes;
                            break;
                        case "max_ack_pending":
                            if (!TryConvertToLong(entry, out var maxAckPending))
                                return new InvalidOperationException($"Expected a parseable size for \"{rawKey}\", got {entry}");
                            limits.MaxAckPending = checked((int)maxAckPending);
                            break;
                        case "cluster_traffic":
                        {
                            var traffic = entry as string ?? string.Empty;
                            switch (traffic)
                            {
                                case "system":
                                case "":
                                    account.NrgAccount = string.Empty;
                                    break;
                                case "owner":
                                    account.NrgAccount = account.Name;
                                    break;
                                default:
                                    return new InvalidOperationException(
                                        $"Expected 'system' or 'owner' string value for \"{rawKey}\", got {entry}");
                            }

                            break;
                        }
                        default:
                            if (!ConfigFlags.AllowUnknownTopLevelField)
                                errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                            break;
                    }
                }

                account.JetStreamLimits = new Dictionary<string, object>(StringComparer.Ordinal)
                {
                    [string.Empty] = limits,
                };

                return null;
        }
    }

    /// <summary>
    /// Parses storage sizes from integer or suffixed-string values.
    /// Mirrors <c>getStorageSize</c> in opts.go.
    /// </summary>
    public static long GetStorageSize(object? value)
    {
        if (TryConvertToLong(value, out var asLong))
            return asLong;

        if (NormalizeConfigValue(value) is not string raw)
            throw new InvalidOperationException("must be int64 or string");

        var s = raw.Trim();
        if (s.Length == 0)
            return 0;

        var suffix = char.ToUpperInvariant(s[^1]);
        var prefix = s[..^1];
        if (!long.TryParse(prefix, out var parsed))
            throw new InvalidOperationException($"invalid size value: {raw}");

        return suffix switch
        {
            'K' => parsed << 10,
            'M' => parsed << 20,
            'G' => parsed << 30,
            'T' => parsed << 40,
            _ => throw new InvalidOperationException("sizes defined as strings must end in K, M, G, T"),
        };
    }

    /// <summary>
    /// Parses server-level JetStream limits.
    /// Mirrors <c>parseJetStreamLimits</c> in opts.go.
    /// </summary>
    public static Exception? ParseJetStreamLimits(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected a map to define JetStreamLimits, got {value?.GetType().Name ?? "null"}");

        options.JetStreamLimits = new JsLimitOpts();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "max_ack_pending":
                    if (TryConvertToLong(entry, out var maxAckPending))
                        options.JetStreamLimits.MaxAckPending = checked((int)maxAckPending);
                    break;
                case "max_ha_assets":
                    if (TryConvertToLong(entry, out var maxHaAssets))
                        options.JetStreamLimits.MaxHaAssets = checked((int)maxHaAssets);
                    break;
                case "max_request_batch":
                    if (TryConvertToLong(entry, out var maxRequestBatch))
                        options.JetStreamLimits.MaxRequestBatch = checked((int)maxRequestBatch);
                    break;
                case "duplicate_window":
                    options.JetStreamLimits.Duplicates = ParseDuration("duplicate_window", entry, errors, warnings: null);
                    break;
                case "batch":
                {
                    var parseError = ParseJetStreamLimitsBatch(entry, options, errors);
                    if (parseError != null)
                        return parseError;
                    break;
                }
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses nested batch limits inside JetStream limits block.
    /// Mirrors <c>parseJetStreamLimitsBatch</c> in opts.go.
    /// </summary>
    public static Exception? ParseJetStreamLimitsBatch(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected a map to define batch limits, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "max_inflight_per_stream":
                    if (TryConvertToLong(entry, out var maxInflightPerStream))
                        options.JetStreamLimits.MaxBatchInflightPerStream = checked((int)maxInflightPerStream);
                    break;
                case "max_inflight_total":
                    if (TryConvertToLong(entry, out var maxInflightTotal))
                        options.JetStreamLimits.MaxBatchInflightTotal = checked((int)maxInflightTotal);
                    break;
                case "max_msgs":
                    if (TryConvertToLong(entry, out var maxBatchSize))
                        options.JetStreamLimits.MaxBatchSize = checked((int)maxBatchSize);
                    break;
                case "timeout":
                    options.JetStreamLimits.MaxBatchTimeout = ParseDuration("timeout", entry, errors, warnings: null);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses JetStream TPM options.
    /// Mirrors <c>parseJetStreamTPM</c> in opts.go.
    /// </summary>
    public static Exception? ParseJetStreamTPM(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected a map to define JetStream TPM, got {value?.GetType().Name ?? "null"}");

        options.JetStreamTpm = new JsTpmOpts();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "keys_file":
                    options.JetStreamTpm.KeysFile = entry as string ?? string.Empty;
                    break;
                case "encryption_password":
                    options.JetStreamTpm.KeyPassword = entry as string ?? string.Empty;
                    break;
                case "srk_password":
                    options.JetStreamTpm.SrkPassword = entry as string ?? string.Empty;
                    break;
                case "pcr":
                    if (TryConvertToLong(entry, out var pcr))
                        options.JetStreamTpm.Pcr = checked((int)pcr);
                    break;
                case "cipher":
                {
                    var parseError = SetJetStreamEkCipher(options, entry);
                    if (parseError != null)
                        return parseError;
                    break;
                }
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses JetStream encryption cipher selection.
    /// Mirrors <c>setJetStreamEkCipher</c> in opts.go.
    /// </summary>
    public static Exception? SetJetStreamEkCipher(ServerOptions options, object? value)
    {
        ArgumentNullException.ThrowIfNull(options);

        var cipher = (NormalizeConfigValue(value) as string ?? string.Empty).ToLowerInvariant();
        switch (cipher)
        {
            case "chacha":
            case "chachapoly":
                options.JetStreamCipher = StoreCipher.ChaCha;
                return null;
            case "aes":
                options.JetStreamCipher = StoreCipher.Aes;
                return null;
            default:
                return new InvalidOperationException($"Unknown cipher type: \"{value}\"");
        }
    }

    /// <summary>
    /// Parses top-level JetStream enablement/configuration.
    /// Mirrors <c>parseJetStream</c> in opts.go.
    /// </summary>
    public static Exception? ParseJetStream(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        var normalized = NormalizeConfigValue(value);
        switch (normalized)
        {
            case bool enabled:
                options.JetStream = enabled;
                return null;
            case string mode:
                switch (mode.Trim().ToLowerInvariant())
                {
                    case "enabled":
                    case "enable":
                        options.JetStream = true;
                        return null;
                    case "disabled":
                    case "disable":
                        options.JetStream = false;
                        return null;
                    default:
                        return new InvalidOperationException(
                            $"Expected 'enabled' or 'disabled' for string value, got '{mode}'");
                }
            default:
                if (!TryGetMap(normalized, out var map))
                {
                    return new InvalidOperationException(
                        $"Expected map, bool or string to define JetStream, got {normalized?.GetType().Name ?? "null"}");
                }

                var enable = true;
                foreach (var (rawKey, rawValue) in map)
                {
                    var key = rawKey.ToLowerInvariant();
                    var entry = NormalizeConfigValue(rawValue);
                    switch (key)
                    {
                        case "strict":
                            if (!TryConvertToBool(entry, out var strictMode))
                                return new InvalidOperationException($"Expected bool for \"{rawKey}\", got {entry}");
                            options.NoJetStreamStrict = !strictMode;
                            break;
                        case "store":
                        case "store_dir":
                        case "storedir":
                            if (!string.IsNullOrEmpty(options.StoreDir))
                                return new InvalidOperationException("Duplicate 'store_dir' configuration");
                            options.StoreDir = entry as string ?? string.Empty;
                            break;
                        case "sync":
                        case "sync_interval":
                            if ((entry as string)?.Equals("always", StringComparison.OrdinalIgnoreCase) == true)
                            {
                                options.SyncInterval = TimeSpan.FromMinutes(2);
                                options.SyncAlways = true;
                            }
                            else
                            {
                                options.SyncInterval = ParseDuration(rawKey, entry, errors, warnings);
                            }

                            options.SyncSet = true;
                            break;
                        case "max_memory_store":
                        case "max_mem_store":
                        case "max_mem":
                            options.JetStreamMaxMemory = GetStorageSize(entry);
                            options.MaxMemSet = true;
                            break;
                        case "max_file_store":
                        case "max_file":
                            options.JetStreamMaxStore = GetStorageSize(entry);
                            options.MaxStoreSet = true;
                            break;
                        case "domain":
                            options.JetStreamDomain = entry as string ?? string.Empty;
                            break;
                        case "enable":
                        case "enabled":
                            if (TryConvertToBool(entry, out var toggle))
                                enable = toggle;
                            break;
                        case "key":
                        case "ek":
                        case "encryption_key":
                            options.JetStreamKey = entry as string ?? string.Empty;
                            break;
                        case "prev_key":
                        case "prev_ek":
                        case "prev_encryption_key":
                            options.JetStreamOldKey = entry as string ?? string.Empty;
                            break;
                        case "cipher":
                        {
                            var parseError = SetJetStreamEkCipher(options, entry);
                            if (parseError != null)
                                return parseError;
                            break;
                        }
                        case "extension_hint":
                            options.JetStreamExtHint = entry as string ?? string.Empty;
                            break;
                        case "limits":
                        {
                            var parseError = ParseJetStreamLimits(entry, options, errors);
                            if (parseError != null)
                                return parseError;
                            break;
                        }
                        case "tpm":
                        {
                            var parseError = ParseJetStreamTPM(entry, options, errors);
                            if (parseError != null)
                                return parseError;
                            break;
                        }
                        case "unique_tag":
                            options.JetStreamUniqueTag = (entry as string ?? string.Empty).Trim().ToLowerInvariant();
                            break;
                        case "max_outstanding_catchup":
                            options.JetStreamMaxCatchup = GetStorageSize(entry);
                            break;
                        case "max_buffered_size":
                            options.StreamMaxBufferedSize = GetStorageSize(entry);
                            break;
                        case "max_buffered_msgs":
                            if (TryConvertToLong(entry, out var bufferedMsgs))
                                options.StreamMaxBufferedMsgs = checked((int)bufferedMsgs);
                            break;
                        case "request_queue_limit":
                            if (TryConvertToLong(entry, out var requestQueueLimit))
                                options.JetStreamRequestQueueLimit = requestQueueLimit;
                            break;
                        case "meta_compact":
                            if (TryConvertToLong(entry, out var compact))
                            {
                                if (compact < 0)
                                    return new InvalidOperationException($"Expected an absolute size for \"{rawKey}\", got {entry}");
                                options.JetStreamMetaCompact = checked((ulong)compact);
                            }

                            break;
                        case "meta_compact_size":
                        {
                            var compactSize = GetStorageSize(entry);
                            if (compactSize < 0)
                                return new InvalidOperationException($"Expected an absolute size for \"{rawKey}\", got {entry}");
                            options.JetStreamMetaCompactSize = checked((ulong)compactSize);
                            break;
                        }
                        case "meta_compact_sync":
                            if (TryConvertToBool(entry, out var compactSync))
                                options.JetStreamMetaCompactSync = compactSync;
                            break;
                        default:
                            if (!ConfigFlags.AllowUnknownTopLevelField)
                                errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                            break;
                    }
                }

                options.JetStream = enable;
                return null;
        }
    }

    /// <summary>
    /// Parses leaf-node configuration.
    /// Mirrors <c>parseLeafNodes</c> in opts.go.
    /// </summary>
    public static Exception? ParseLeafNodes(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected map to define a leafnode, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "listen":
                {
                    try
                    {
                        var (host, port) = ParseListen(entry);
                        options.LeafNode.Host = host;
                        options.LeafNode.Port = port;
                    }
                    catch (Exception ex)
                    {
                        errors?.Add(ex);
                    }

                    break;
                }
                case "port":
                    if (TryConvertToLong(entry, out var leafPort))
                        options.LeafNode.Port = checked((int)leafPort);
                    break;
                case "host":
                case "net":
                    options.LeafNode.Host = entry as string ?? string.Empty;
                    break;
                case "authorization":
                {
                    var auth = ParseLeafAuthorization(entry, errors, warnings);
                    if (auth == null)
                        break;
                    options.LeafNode.Username = auth.Username;
                    options.LeafNode.Password = auth.Password;
                    options.LeafNode.ProxyRequired = auth.ProxyRequired;
                    options.LeafNode.AuthTimeout = auth.TimeoutSeconds;
                    options.LeafNode.Account = auth.AccountName;
                    options.LeafNode.Users = auth.Users;
                    options.LeafNode.Nkey = auth.Nkey;
                    break;
                }
                case "remotes":
                    options.LeafNode.Remotes = ParseRemoteLeafNodes(entry, errors, warnings);
                    break;
                case "reconnect":
                case "reconnect_delay":
                case "reconnect_interval":
                    options.LeafNode.ReconnectInterval = ParseDuration("reconnect", entry, errors, warnings);
                    break;
                case "tls":
                {
                    var (config, tlsOpts, parseError) = GetTLSConfig(entry, requireClientCertificate: false);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    options.LeafNode.TlsConfig = config;
                    options.LeafNode.TlsTimeout = tlsOpts?.Timeout > 0
                        ? tlsOpts.Timeout
                        : ServerConstants.DefaultLeafTlsTimeout.TotalSeconds;
                    options.LeafNode.TlsMap = tlsOpts?.Map ?? false;
                    options.LeafNode.TlsPinnedCerts = tlsOpts?.PinnedCerts;
                    options.LeafNode.TlsHandshakeFirst = tlsOpts?.HandshakeFirst ?? false;
                    options.LeafNode.TlsHandshakeFirstFallback = tlsOpts?.FallbackDelay ?? TimeSpan.Zero;
                    options.LeafNode.TlsConfigOpts = tlsOpts;
                    break;
                }
                case "leafnode_advertise":
                case "advertise":
                    options.LeafNode.Advertise = entry as string ?? string.Empty;
                    break;
                case "no_advertise":
                    if (TryConvertToBool(entry, out var noAdvertise))
                    {
                        options.LeafNode.NoAdvertise = noAdvertise;
                        TrackExplicitVal(options.InConfig, "LeafNode.NoAdvertise", noAdvertise);
                    }

                    break;
                case "min_version":
                case "minimum_version":
                    options.LeafNode.MinVersion = entry as string ?? string.Empty;
                    break;
                case "compression":
                {
                    var parseError = ParseCompression(
                        options.LeafNode.Compression,
                        CompressionModes.S2Auto,
                        "compression",
                        entry);
                    if (parseError != null)
                        errors?.Add(parseError);
                    break;
                }
                case "isolate_leafnode_interest":
                case "isolate":
                    if (TryConvertToBool(entry, out var isolate))
                        options.LeafNode.IsolateLeafnodeInterest = isolate;
                    break;
                case "write_deadline":
                    options.LeafNode.WriteDeadline = ParseDuration("write_deadline", entry, errors, warnings);
                    break;
                case "write_timeout":
                    options.LeafNode.WriteTimeout = ParseWriteDeadlinePolicy(entry as string ?? string.Empty, errors);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses leaf-node authorization block.
    /// Mirrors <c>parseLeafAuthorization</c> in opts.go.
    /// </summary>
    public static LeafAuthorization? ParseLeafAuthorization(
        object? value,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        if (!TryGetMap(value, out var map))
        {
            errors?.Add(new InvalidOperationException("leafnode authorization should be a map"));
            return null;
        }

        var auth = new LeafAuthorization();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "user":
                case "username":
                    auth.Username = entry as string ?? string.Empty;
                    break;
                case "pass":
                case "password":
                    auth.Password = entry as string ?? string.Empty;
                    break;
                case "nkey":
                    auth.Nkey = entry as string ?? string.Empty;
                    break;
                case "timeout":
                    switch (entry)
                    {
                        case long l:
                            auth.TimeoutSeconds = l;
                            break;
                        case double d:
                            auth.TimeoutSeconds = d;
                            break;
                        case string s:
                            auth.TimeoutSeconds = ParseDuration("timeout", s, errors, warnings).TotalSeconds;
                            break;
                        default:
                            errors?.Add(new InvalidOperationException("error parsing leafnode authorization config, 'timeout' wrong type"));
                            break;
                    }

                    if (auth.TimeoutSeconds > TimeSpan.FromMinutes(1).TotalSeconds)
                    {
                        warnings?.Add(new InvalidOperationException(
                            $"timeout of {entry} ({auth.TimeoutSeconds} seconds) is high, consider keeping it under 60 seconds"));
                    }

                    break;
                case "users":
                    auth.Users = ParseLeafUsers(entry, errors);
                    break;
                case "account":
                    auth.AccountName = entry as string ?? string.Empty;
                    break;
                case "proxy_required":
                    if (TryConvertToBool(entry, out var proxyRequired))
                        auth.ProxyRequired = proxyRequired;
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return auth;
    }

    /// <summary>
    /// Parses leaf-node authorization users list.
    /// Mirrors <c>parseLeafUsers</c> in opts.go.
    /// </summary>
    public static List<User> ParseLeafUsers(object? value, ICollection<Exception>? errors = null)
    {
        if (!TryGetArray(value, out var usersArray))
            throw new InvalidOperationException($"Expected users field to be an array, got {value?.GetType().Name ?? "null"}");

        var users = new List<User>(usersArray.Count);
        foreach (var userEntry in usersArray)
        {
            if (!TryGetMap(userEntry, out var userMap))
            {
                errors?.Add(new InvalidOperationException($"Expected user entry to be a map/struct, got {userEntry}"));
                continue;
            }

            var user = new User();
            foreach (var (rawKey, rawValue) in userMap)
            {
                var key = rawKey.ToLowerInvariant();
                var entry = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "user":
                    case "username":
                        user.Username = entry as string ?? string.Empty;
                        break;
                    case "pass":
                    case "password":
                        user.Password = entry as string ?? string.Empty;
                        break;
                    case "account":
                        user.Account = new Account { Name = entry as string ?? string.Empty };
                        break;
                    case "proxy_required":
                        if (TryConvertToBool(entry, out var proxyRequired))
                            user.ProxyRequired = proxyRequired;
                        break;
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            users.Add(user);
        }

        return users;
    }

    /// <summary>
    /// Parses remote leaf-node definitions.
    /// Mirrors <c>parseRemoteLeafNodes</c> in opts.go.
    /// </summary>
    public static List<RemoteLeafOpts> ParseRemoteLeafNodes(
        object? value,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        if (!TryGetArray(value, out var remoteArray))
            throw new InvalidOperationException($"Expected remotes field to be an array, got {value?.GetType().Name ?? "null"}");

        var remotes = new List<RemoteLeafOpts>(remoteArray.Count);
        foreach (var remoteEntry in remoteArray)
        {
            if (!TryGetMap(remoteEntry, out var remoteMap))
            {
                errors?.Add(new InvalidOperationException(
                    $"Expected remote leafnode entry to be a map/struct, got {remoteEntry}"));
                continue;
            }

            var remote = new RemoteLeafOpts();
            foreach (var (rawKey, rawValue) in remoteMap)
            {
                var key = rawKey.ToLowerInvariant();
                var entry = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "no_randomize":
                    case "dont_randomize":
                        if (TryConvertToBool(entry, out var noRandomize))
                            remote.NoRandomize = noRandomize;
                        break;
                    case "url":
                    case "urls":
                        if (entry is string singleUrl)
                        {
                            remote.Urls.Add(ParseURL(singleUrl, "leafnode"));
                        }
                        else if (TryGetArray(entry, out var urlArray))
                        {
                            remote.Urls = ParseURLs(urlArray, "leafnode", warnings, errors);
                        }

                        break;
                    case "account":
                    case "local":
                        remote.LocalAccount = entry as string ?? string.Empty;
                        break;
                    case "creds":
                    case "credentials":
                        remote.Credentials = ExpandPath(entry as string ?? string.Empty);
                        break;
                    case "nkey":
                    case "seed":
                        remote.Nkey = entry as string ?? string.Empty;
                        break;
                    case "tls":
                    {
                        var (config, tlsOpts, parseError) = GetTLSConfig(entry, requireClientCertificate: false);
                        if (parseError != null)
                        {
                            errors?.Add(parseError);
                            break;
                        }

                        remote.TlsConfig = config;
                        remote.TlsTimeout = tlsOpts?.Timeout > 0
                            ? tlsOpts.Timeout
                            : ServerConstants.DefaultLeafTlsTimeout.TotalSeconds;
                        remote.TlsHandshakeFirst = tlsOpts?.HandshakeFirst ?? false;
                        remote.TlsConfigOpts = tlsOpts;
                        break;
                    }
                    case "hub":
                        if (TryConvertToBool(entry, out var hub))
                            remote.Hub = hub;
                        break;
                    case "deny_imports":
                    case "deny_import":
                        remote.DenyImports = ParseStringList(entry);
                        break;
                    case "deny_exports":
                    case "deny_export":
                        remote.DenyExports = ParseStringList(entry);
                        break;
                    case "ws_compress":
                    case "ws_compression":
                    case "websocket_compress":
                    case "websocket_compression":
                        if (TryConvertToBool(entry, out var wsCompression))
                            remote.Websocket.Compression = wsCompression;
                        break;
                    case "ws_no_masking":
                    case "websocket_no_masking":
                        if (TryConvertToBool(entry, out var wsNoMasking))
                            remote.Websocket.NoMasking = wsNoMasking;
                        break;
                    case "jetstream_cluster_migrate":
                    case "js_cluster_migrate":
                        if (TryConvertToBool(entry, out var migrateToggle))
                        {
                            remote.JetStreamClusterMigrate = migrateToggle;
                        }
                        else if (TryGetMap(entry, out var migrateMap))
                        {
                            remote.JetStreamClusterMigrate = true;
                            if (migrateMap.TryGetValue("leader_migrate_delay", out var delayValue))
                            {
                                remote.JetStreamClusterMigrateDelay = ParseDuration(
                                    "leader_migrate_delay",
                                    delayValue,
                                    errors,
                                    warnings);
                            }
                        }
                        else
                        {
                            errors?.Add(new InvalidOperationException(
                                $"Expected boolean or map for jetstream_cluster_migrate, got {entry?.GetType().Name ?? "null"}"));
                        }

                        break;
                    case "isolate_leafnode_interest":
                    case "isolate":
                        if (TryConvertToBool(entry, out var localIsolation))
                            remote.LocalIsolation = localIsolation;
                        break;
                    case "request_isolation":
                        if (TryConvertToBool(entry, out var requestIsolation))
                            remote.RequestIsolation = requestIsolation;
                        break;
                    case "compression":
                    {
                        var parseError = ParseCompression(
                            remote.Compression,
                            CompressionModes.S2Auto,
                            "compression",
                            entry);
                        if (parseError != null)
                            errors?.Add(parseError);
                        break;
                    }
                    case "first_info_timeout":
                        remote.FirstInfoTimeout = ParseDuration("first_info_timeout", entry, errors, warnings);
                        break;
                    case "disabled":
                        if (TryConvertToBool(entry, out var disabled))
                            remote.Disabled = disabled;
                        break;
                    case "proxy":
                        if (TryGetMap(entry, out var proxyMap))
                        {
                            foreach (var (proxyKeyRaw, proxyValueRaw) in proxyMap)
                            {
                                var proxyKey = proxyKeyRaw.ToLowerInvariant();
                                var proxyValue = NormalizeConfigValue(proxyValueRaw);
                                switch (proxyKey)
                                {
                                    case "url":
                                        remote.Proxy.Url = proxyValue as string ?? string.Empty;
                                        break;
                                    case "username":
                                        remote.Proxy.Username = proxyValue as string ?? string.Empty;
                                        break;
                                    case "password":
                                        remote.Proxy.Password = proxyValue as string ?? string.Empty;
                                        break;
                                    case "timeout":
                                        remote.Proxy.Timeout = ParseDuration("proxy timeout", proxyValue, errors, warnings);
                                        break;
                                    default:
                                        if (!ConfigFlags.AllowUnknownTopLevelField)
                                            errors?.Add(new InvalidOperationException($"unknown field \"{proxyKeyRaw}\""));
                                        break;
                                }
                            }
                        }

                        break;
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            remotes.Add(remote);
        }

        return remotes;
    }

    /// <summary>
    /// Parses TLS config block and builds runtime TLS options.
    /// Mirrors <c>getTLSConfig</c> in opts.go.
    /// </summary>
    public static (SslServerAuthenticationOptions? Config, TlsConfigOpts? Options, Exception? Error) GetTLSConfig(
        object? value,
        bool requireClientCertificate = true)
    {
        if (!TryGetMap(value, out var map))
            return (null, null, new InvalidOperationException("TLS options should be a map"));

        var tlsOpts = new TlsConfigOpts();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "cert_file":
                case "cert":
                    tlsOpts.CertFile = entry as string ?? string.Empty;
                    break;
                case "key_file":
                case "key":
                    tlsOpts.KeyFile = entry as string ?? string.Empty;
                    break;
                case "ca_file":
                case "ca":
                    tlsOpts.CaFile = entry as string ?? string.Empty;
                    break;
                case "verify":
                    if (TryConvertToBool(entry, out var verify))
                        tlsOpts.Verify = verify;
                    break;
                case "map":
                    if (TryConvertToBool(entry, out var mapCert))
                        tlsOpts.Map = mapCert;
                    break;
                case "timeout":
                    if (entry is string timeoutString)
                    {
                        tlsOpts.Timeout = ParseDuration("tls timeout", timeoutString).TotalSeconds;
                    }
                    else if (TryConvertToDouble(entry, out var timeoutSeconds))
                    {
                        tlsOpts.Timeout = timeoutSeconds;
                    }

                    break;
                case "handshake_first":
                    if (TryConvertToBool(entry, out var handshakeFirst))
                        tlsOpts.HandshakeFirst = handshakeFirst;
                    break;
                case "handshake_first_fallback":
                case "fallback_delay":
                    tlsOpts.FallbackDelay = ParseDuration("fallback_delay", entry);
                    break;
                case "pinned_certs":
                    tlsOpts.PinnedCerts = new PinnedCertSet(ParseStringList(entry));
                    break;
                case "min_version":
                    if (entry is string minVersion)
                    {
                        try
                        {
                            tlsOpts.MinVersion = TlsVersionJsonConverter.Parse(minVersion);
                        }
                        catch (Exception ex)
                        {
                            return (null, null, ex);
                        }
                    }

                    break;
            }
        }

        var enabledProtocols = tlsOpts.MinVersion switch
        {
            SslProtocols.Tls13 => SslProtocols.Tls13,
            SslProtocols.Tls12 => SslProtocols.Tls12 | SslProtocols.Tls13,
            _ => SslProtocols.Tls12 | SslProtocols.Tls13,
        };

        var config = new SslServerAuthenticationOptions
        {
            EnabledSslProtocols = enabledProtocols,
            ClientCertificateRequired = requireClientCertificate || tlsOpts.Verify,
            CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
        };

        return (config, tlsOpts, null);
    }

    /// <summary>
    /// Parses list of remote gateways.
    /// Mirrors <c>parseGateways</c> in opts.go.
    /// </summary>
    public static List<RemoteGatewayOpts> ParseGateways(
        object? value,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        if (!TryGetArray(value, out var gatewayArray))
            throw new InvalidOperationException($"Expected gateways field to be an array, got {value?.GetType().Name ?? "null"}");

        var gateways = new List<RemoteGatewayOpts>(gatewayArray.Count);
        foreach (var gatewayEntry in gatewayArray)
        {
            if (!TryGetMap(gatewayEntry, out var gatewayMap))
            {
                errors?.Add(new InvalidOperationException($"Expected gateway entry to be a map/struct, got {gatewayEntry}"));
                continue;
            }

            var gateway = new RemoteGatewayOpts();
            foreach (var (rawKey, rawValue) in gatewayMap)
            {
                var key = rawKey.ToLowerInvariant();
                var entry = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "name":
                        gateway.Name = entry as string ?? string.Empty;
                        break;
                    case "tls":
                    {
                        var (config, tlsOpts, parseError) = GetTLSConfig(entry);
                        if (parseError != null)
                        {
                            errors?.Add(parseError);
                            break;
                        }

                        gateway.TlsConfig = config;
                        gateway.TlsTimeout = tlsOpts?.Timeout ?? 0;
                        gateway.TlsConfigOpts = tlsOpts;
                        break;
                    }
                    case "url":
                        gateway.Urls.Add(ParseURL(entry as string ?? string.Empty, "gateway"));
                        break;
                    case "urls":
                        if (TryGetArray(entry, out var urlArray))
                            gateway.Urls = ParseURLs(urlArray, "gateway", warnings, errors);
                        break;
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            gateways.Add(gateway);
        }

        return gateways;
    }

    /// <summary>
    /// Maps parsed pub/sub permissions to route import/export permissions.
    /// Mirrors <c>setClusterPermissions</c> in opts.go.
    /// </summary>
    public static void SetClusterPermissions(ClusterOpts options, Permissions permissions)
    {
        ArgumentNullException.ThrowIfNull(options);
        ArgumentNullException.ThrowIfNull(permissions);

        options.Permissions = new RoutePermissions
        {
            Import = permissions.Publish?.Clone(),
            Export = permissions.Subscribe?.Clone(),
        };
    }

    // -------------------------------------------------------------------------
    // Batch 6: opts.go package-level parse/config helpers (F3)
    // -------------------------------------------------------------------------

    /// <summary>
    /// Returns true for reserved account names.
    /// Mirrors <c>isReservedAccount</c> in opts.go.
    /// </summary>
    public static bool IsReservedAccount(string name) =>
        string.Equals(name, ServerConstants.DefaultGlobalAccount, StringComparison.Ordinal);

    /// <summary>
    /// Parsed account export entry used during account-config parsing.
    /// </summary>
    public sealed class AccountExportConfig
    {
        public Account? Account { get; set; }
        public string Subject { get; set; } = string.Empty;
        public List<string> AccountNames { get; set; } = [];
        public ServiceRespType ResponseType { get; set; } = ServiceRespType.Singleton;
        public object? Latency { get; set; }
        public TimeSpan ResponseThreshold { get; set; }
        public uint AccountTokenPosition { get; set; }
        public bool AllowTrace { get; set; }
    }

    /// <summary>
    /// Parsed account stream-import entry used during account-config parsing.
    /// </summary>
    public sealed class AccountImportStreamConfig
    {
        public Account? Account { get; set; }
        public string AccountName { get; set; } = string.Empty;
        public string Subject { get; set; } = string.Empty;
        public string Prefix { get; set; } = string.Empty;
        public string To { get; set; } = string.Empty;
        public bool AllowTrace { get; set; }
    }

    /// <summary>
    /// Parsed account service-import entry used during account-config parsing.
    /// </summary>
    public sealed class AccountImportServiceConfig
    {
        public Account? Account { get; set; }
        public string AccountName { get; set; } = string.Empty;
        public string Subject { get; set; } = string.Empty;
        public string To { get; set; } = string.Empty;
        public bool Share { get; set; }
    }

    /// <summary>
    /// Parsed authorization block used for top-level/config-subtree authorization parsing.
    /// </summary>
    public sealed class ParsedAuthorizationBlock
    {
        public string User { get; set; } = string.Empty;
        public string Pass { get; set; } = string.Empty;
        public string Token { get; set; } = string.Empty;
        public double TimeoutSeconds { get; set; }
        public bool ProxyRequired { get; set; }
        public List<User> Users { get; set; } = [];
        public List<NkeyUser> Nkeys { get; set; } = [];
        public Permissions? DefaultPermissions { get; set; }
        public AuthCalloutOpts? Callout { get; set; }
    }

    /// <summary>
    /// Parses a weighted account mapping destination entry.
    /// Mirrors <c>parseAccountMapDest</c> in opts.go.
    /// </summary>
    public static MapDest? ParseAccountMapDest(object? value, ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            errors?.Add(new InvalidOperationException("Expected an entry for the mapping destination"));
            return null;
        }

        var mdest = new MapDest();
        var sawWeight = false;
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "dest":
                case "destination":
                    if (entry is string subject)
                    {
                        mdest.Subject = subject;
                    }
                    else
                    {
                        errors?.Add(new InvalidOperationException("mapping destination must be a string"));
                        return null;
                    }

                    break;
                case "weight":
                {
                    long parsedWeight;
                    switch (entry)
                    {
                        case string weightString:
                        {
                            var normalizedWeight = weightString.Trim().TrimEnd('%');
                            if (!long.TryParse(normalizedWeight, out parsedWeight))
                            {
                                errors?.Add(new InvalidOperationException(
                                    $"Invalid weight \"{weightString}\" for mapping destination"));
                                return null;
                            }

                            break;
                        }
                        default:
                            if (!TryConvertToLong(entry, out parsedWeight))
                            {
                                errors?.Add(new InvalidOperationException(
                                    $"Unknown entry type for weight \"{entry?.GetType().Name ?? "null"}\""));
                                return null;
                            }

                            break;
                    }

                    if (parsedWeight is > 100 or < 0)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Invalid weight {parsedWeight} for mapping destination"));
                        return null;
                    }

                    mdest.Weight = (byte)parsedWeight;
                    sawWeight = true;
                    break;
                }
                case "cluster":
                    mdest.Cluster = entry as string ?? string.Empty;
                    break;
                default:
                    errors?.Add(new InvalidOperationException(
                        $"Unknown field \"{rawKey}\" for mapping destination"));
                    return null;
            }
        }

        if (!sawWeight)
        {
            errors?.Add(new InvalidOperationException(
                $"Missing weight for mapping destination \"{mdest.Subject}\""));
            return null;
        }

        return mdest;
    }

    /// <summary>
    /// Parses account subject mappings.
    /// Mirrors <c>parseAccountMappings</c> in opts.go.
    /// </summary>
    public static Exception? ParseAccountMappings(
        object? value,
        Account account,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(account);
        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected account mappings map, got {value?.GetType().Name ?? "null"}");

        foreach (var (subject, rawDestination) in map)
        {
            if (!SubscriptionIndex.IsValidSubject(subject))
            {
                errors?.Add(new InvalidOperationException($"Subject \"{subject}\" is not a valid subject"));
                continue;
            }

            var destination = NormalizeConfigValue(rawDestination);
            switch (destination)
            {
                case string mappedSubject:
                {
                    var mapError = account.AddMapping(subject, mappedSubject);
                    if (mapError != null)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Error adding mapping for \"{subject}\" to \"{mappedSubject}\": {mapError.Message}",
                            mapError));
                    }

                    break;
                }
                default:
                    if (TryGetArray(destination, out var destinationArray))
                    {
                        var destinations = new List<MapDest>(destinationArray.Count);
                        foreach (var entry in destinationArray)
                        {
                            var parsedDestination = ParseAccountMapDest(entry, errors);
                            if (parsedDestination != null)
                                destinations.Add(parsedDestination);
                        }

                        if (destinations.Count == 0)
                            break;

                        var mapError = account.AddWeightedMappings(subject, [.. destinations]);
                        if (mapError != null)
                        {
                            errors?.Add(new InvalidOperationException(
                                $"Error adding mapping for \"{subject}\": {mapError.Message}",
                                mapError));
                        }

                        break;
                    }

                    if (TryGetMap(destination, out _))
                    {
                        var parsedDestination = ParseAccountMapDest(destination, errors);
                        if (parsedDestination == null)
                            break;

                        var mapError = account.AddWeightedMappings(subject, parsedDestination);
                        if (mapError != null)
                        {
                            errors?.Add(new InvalidOperationException(
                                $"Error adding mapping for \"{subject}\": {mapError.Message}",
                                mapError));
                        }

                        break;
                    }

                    errors?.Add(new InvalidOperationException(
                        $"Unknown type {destination?.GetType().Name ?? "null"} for mapping destination"));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses account-level connection/subscription/payload limits.
    /// Mirrors <c>parseAccountLimits</c> in opts.go.
    /// </summary>
    public static Exception? ParseAccountLimits(
        object? value,
        Account account,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(account);
        if (!TryGetMap(value, out var map))
            return new InvalidOperationException(
                $"Expected account limits to be a map/struct, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            if (!TryConvertToLong(entry, out var numericValue))
            {
                errors?.Add(new InvalidOperationException(
                    $"Expected numeric value parsing account limit \"{rawKey}\""));
                continue;
            }

            switch (key)
            {
                case "max_connections":
                case "max_conn":
                    account.MaxConnections = checked((int)numericValue);
                    break;
                case "max_subscriptions":
                case "max_subs":
                    account.MaxSubscriptions = checked((int)numericValue);
                    break;
                case "max_payload":
                case "max_pay":
                    account.MaxPayload = checked((int)numericValue);
                    break;
                case "max_leafnodes":
                case "max_leafs":
                    account.MaxLeafNodes = checked((int)numericValue);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Unknown field \"{rawKey}\" parsing account limits"));
                    }

                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses account message trace destination/sampling configuration.
    /// Mirrors <c>parseAccountMsgTrace</c> in opts.go.
    /// </summary>
    public static Exception? ParseAccountMsgTrace(object? value, string topKey, Account account)
    {
        ArgumentNullException.ThrowIfNull(account);

        static Exception? ProcessDestination(Account targetAccount, string key, object? rawValue)
        {
            if (rawValue is not string destination)
            {
                return new InvalidOperationException(
                    $"Field \"{key}\" should be a string, got {rawValue?.GetType().Name ?? "null"}");
            }

            if (!SubscriptionIndex.IsValidPublishSubject(destination))
                return new InvalidOperationException($"Trace destination \"{destination}\" is not valid");

            targetAccount.SetMessageTraceDestination(destination);
            return null;
        }

        static Exception? ProcessSampling(Account targetAccount, int sampling)
        {
            if (sampling is <= 0 or > 100)
            {
                return new InvalidOperationException(
                    $"Trace destination sampling value {sampling} is invalid, needs to be [1..100]");
            }

            targetAccount.SetMessageTraceSampling(sampling);
            return null;
        }

        var normalized = NormalizeConfigValue(value);
        switch (normalized)
        {
            case string:
                return ProcessDestination(account, topKey, normalized);
            default:
                if (!TryGetMap(normalized, out var map))
                {
                    return new InvalidOperationException(
                        $"Expected account message trace \"{topKey}\" to be a string or map/struct, got {normalized?.GetType().Name ?? "null"}");
                }

                foreach (var (rawKey, rawValue) in map)
                {
                    var key = rawKey.ToLowerInvariant();
                    var entry = NormalizeConfigValue(rawValue);
                    switch (key)
                    {
                        case "dest":
                        {
                            var destinationError = ProcessDestination(account, rawKey, entry);
                            if (destinationError != null)
                                return destinationError;
                            break;
                        }
                        case "sampling":
                        {
                            int parsedSampling;
                            switch (entry)
                            {
                                case string samplingString:
                                {
                                    var normalizedSampling = samplingString.Trim().TrimEnd('%');
                                    if (!int.TryParse(normalizedSampling, out parsedSampling))
                                    {
                                        return new InvalidOperationException(
                                            $"Invalid trace destination sampling value \"{samplingString}\"");
                                    }

                                    break;
                                }
                                default:
                                    if (!TryConvertToLong(entry, out var longSampling))
                                    {
                                        return new InvalidOperationException(
                                            $"Trace destination sampling field \"{rawKey}\" should be an integer or a percentage, got {entry?.GetType().Name ?? "null"}");
                                    }

                                    parsedSampling = checked((int)longSampling);
                                    break;
                            }

                            var samplingError = ProcessSampling(account, parsedSampling);
                            if (samplingError != null)
                                return samplingError;
                            break;
                        }
                        default:
                            if (!ConfigFlags.AllowUnknownTopLevelField)
                            {
                                return new InvalidOperationException(
                                    $"Unknown field \"{rawKey}\" parsing account message trace map/struct \"{topKey}\"");
                            }

                            break;
                    }
                }

                return null;
        }
    }

    /// <summary>
    /// Parses the top-level <c>accounts</c> block.
    /// Mirrors <c>parseAccounts</c> in opts.go.
    /// </summary>
    public static Exception? ParseAccounts(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        var pendingImportStreams = new List<AccountImportStreamConfig>();
        var pendingImportServices = new List<AccountImportServiceConfig>();
        var pendingExportStreams = new List<AccountExportConfig>();
        var pendingExportServices = new List<AccountExportConfig>();

        var normalized = NormalizeConfigValue(value);
        if (TryGetArray(normalized, out var accountArray))
        {
            var seen = new HashSet<string>(StringComparer.Ordinal);
            foreach (var accountEntry in accountArray)
            {
                var accountName = NormalizeConfigValue(accountEntry) as string ?? string.Empty;
                if (string.IsNullOrWhiteSpace(accountName))
                {
                    errors?.Add(new InvalidOperationException("Expected account name to be a string"));
                    continue;
                }

                if (IsReservedAccount(accountName))
                {
                    errors?.Add(new InvalidOperationException($"\"{accountName}\" is a reserved account"));
                    continue;
                }

                if (!seen.Add(accountName))
                {
                    errors?.Add(new InvalidOperationException($"Duplicate Account Entry: {accountName}"));
                    continue;
                }

                options.Accounts.Add(Account.NewAccount(accountName));
            }

            return null;
        }

        if (!TryGetMap(normalized, out var accountsMap))
        {
            return new InvalidOperationException(
                $"Expected accounts to be an array or map, got {normalized?.GetType().Name ?? "null"}");
        }

        options.Users ??= [];
        options.Nkeys ??= [];
        var identities = SetupUsersAndNKeysDuplicateCheckMap(options);

        foreach (var (accountName, accountValueRaw) in accountsMap)
        {
            var accountValue = NormalizeConfigValue(accountValueRaw);
            if (!TryGetMap(accountValue, out var accountMap))
            {
                errors?.Add(new InvalidOperationException("Expected map entries for accounts"));
                continue;
            }

            if (IsReservedAccount(accountName))
            {
                errors?.Add(new InvalidOperationException($"\"{accountName}\" is a reserved account"));
                continue;
            }

            var account = Account.NewAccount(accountName);
            options.Accounts.Add(account);

            var parsedUsers = new List<User>();
            var parsedNkeys = new List<NkeyUser>();

            foreach (var (rawKey, rawValue) in accountMap)
            {
                var key = rawKey.ToLowerInvariant();
                var entry = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "nkey":
                    {
                        var accountKey = entry as string ?? string.Empty;
                        if (!IsLikelyPublicNkey(accountKey, 'A'))
                        {
                            errors?.Add(new InvalidOperationException(
                                $"Not a valid public nkey for an account: \"{accountKey}\""));
                            break;
                        }

                        account.Nkey = accountKey;
                        break;
                    }
                    case "imports":
                    {
                        var (importStreams, importServices, importError) = ParseAccountImports(entry, account, errors);
                        if (importError != null)
                        {
                            errors?.Add(importError);
                            break;
                        }

                        pendingImportStreams.AddRange(importStreams);
                        pendingImportServices.AddRange(importServices);
                        break;
                    }
                    case "exports":
                    {
                        var (exportStreams, exportServices, exportError) = ParseAccountExports(entry, account, errors);
                        if (exportError != null)
                        {
                            errors?.Add(exportError);
                            break;
                        }

                        pendingExportStreams.AddRange(exportStreams);
                        pendingExportServices.AddRange(exportServices);
                        break;
                    }
                    case "jetstream":
                    {
                        var jsError = ParseJetStreamForAccount(entry, account, errors);
                        if (jsError != null)
                            errors?.Add(jsError);
                        break;
                    }
                    case "users":
                    {
                        var (accountNkeys, accountUsers, usersError) = ParseUsers(entry, errors);
                        if (usersError != null)
                        {
                            errors?.Add(usersError);
                            break;
                        }

                        parsedUsers = accountUsers;
                        parsedNkeys = accountNkeys;
                        break;
                    }
                    case "default_permissions":
                    {
                        var permissions = ParsePermissionsValue(entry, errors);
                        if (permissions != null)
                            account.DefaultPerms = permissions;
                        break;
                    }
                    case "mappings":
                    case "maps":
                    {
                        var mappingsError = ParseAccountMappings(entry, account, errors);
                        if (mappingsError != null)
                            errors?.Add(mappingsError);
                        break;
                    }
                    case "limits":
                    {
                        var limitsError = ParseAccountLimits(entry, account, errors);
                        if (limitsError != null)
                            errors?.Add(limitsError);
                        break;
                    }
                    case "msg_trace":
                    case "trace_dest":
                    {
                        var traceError = ParseAccountMsgTrace(entry, key, account);
                        if (traceError != null)
                        {
                            errors?.Add(traceError);
                            break;
                        }

                        if (!string.IsNullOrEmpty(account.GetMessageTraceDestination()) &&
                            account.GetMessageTraceSampling() == 0)
                        {
                            account.SetMessageTraceSampling(100);
                        }
                        else if (account.GetMessageTraceSampling() > 0 &&
                                 string.IsNullOrEmpty(account.GetMessageTraceDestination()))
                        {
                            warnings?.Add(new InvalidOperationException(
                                "Trace destination sampling ignored since no destination was set"));
                            account.SetMessageTraceSampling(0);
                        }

                        break;
                    }
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            if (parsedNkeys.Count > 0 || parsedUsers.Count > 0)
            {
                if (!string.IsNullOrEmpty(options.Username))
                    errors?.Add(new InvalidOperationException("Cannot have a single user/pass and accounts"));
                if (!string.IsNullOrEmpty(options.Authorization))
                    errors?.Add(new InvalidOperationException("Cannot have a token and accounts"));
            }

            ApplyDefaultPermissions(parsedUsers, parsedNkeys, account.DefaultPerms);

            foreach (var nkeyUser in parsedNkeys)
            {
                if (!identities.Add(nkeyUser.Nkey))
                {
                    errors?.Add(new InvalidOperationException($"Duplicate nkey \"{nkeyUser.Nkey}\" detected"));
                    continue;
                }

                nkeyUser.Account = account;
                options.Nkeys.Add(nkeyUser);
            }

            foreach (var user in parsedUsers)
            {
                if (!identities.Add(user.Username))
                {
                    errors?.Add(new InvalidOperationException($"Duplicate user \"{user.Username}\" detected"));
                    continue;
                }

                user.Account = account;
                options.Users.Add(user);
            }
        }

        if (errors is { Count: > 0 })
            return null;

        var accountLookup = options.Accounts.ToDictionary(a => a.Name, StringComparer.Ordinal);

        foreach (var streamExport in pendingExportStreams)
        {
            if (streamExport.Account == null)
                continue;

            streamExport.Account.Exports.Streams ??= new Dictionary<string, StreamExport>(StringComparer.Ordinal);
            var export = new StreamExport
            {
                AccountPosition = streamExport.AccountTokenPosition,
            };

            if (streamExport.AccountNames.Count > 0)
            {
                export.Approved = new Dictionary<string, Account>(StringComparer.Ordinal);
                foreach (var accountName in streamExport.AccountNames)
                {
                    if (!accountLookup.TryGetValue(accountName, out var approvedAccount))
                    {
                        errors?.Add(new InvalidOperationException(
                            $"\"{accountName}\" account not defined for stream export"));
                        continue;
                    }

                    export.Approved[accountName] = approvedAccount;
                }
            }

            streamExport.Account.Exports.Streams[streamExport.Subject] = export;
        }

        foreach (var serviceExport in pendingExportServices)
        {
            if (serviceExport.Account == null)
                continue;

            serviceExport.Account.Exports.Services ??= new Dictionary<string, ServiceExportEntry>(StringComparer.Ordinal);
            var export = new ServiceExportEntry
            {
                Account = serviceExport.Account,
                ResponseType = serviceExport.ResponseType,
                Latency = serviceExport.Latency as InternalServiceLatency,
                ResponseThreshold = serviceExport.ResponseThreshold,
                AllowTrace = serviceExport.AllowTrace,
                AccountPosition = serviceExport.AccountTokenPosition,
            };

            if (serviceExport.AccountNames.Count > 0)
            {
                export.Approved = new Dictionary<string, Account>(StringComparer.Ordinal);
                foreach (var accountName in serviceExport.AccountNames)
                {
                    if (!accountLookup.TryGetValue(accountName, out var approvedAccount))
                    {
                        errors?.Add(new InvalidOperationException(
                            $"\"{accountName}\" account not defined for service export"));
                        continue;
                    }

                    export.Approved[accountName] = approvedAccount;
                }
            }

            serviceExport.Account.Exports.Services[serviceExport.Subject] = export;
        }

        foreach (var streamImport in pendingImportStreams)
        {
            if (streamImport.Account == null)
                continue;

            if (!accountLookup.TryGetValue(streamImport.AccountName, out var importedAccount))
            {
                errors?.Add(new InvalidOperationException(
                    $"\"{streamImport.AccountName}\" account not defined for stream import"));
                continue;
            }

            streamImport.Account.Imports.Streams ??= [];
            var targetSubject = !string.IsNullOrEmpty(streamImport.To)
                ? streamImport.To
                : !string.IsNullOrEmpty(streamImport.Prefix)
                    ? streamImport.Prefix
                    : streamImport.Subject;

            streamImport.Account.Imports.Streams.Add(new StreamImportEntry
            {
                Account = importedAccount,
                From = streamImport.Subject,
                To = targetSubject,
                AllowTrace = streamImport.AllowTrace,
            });
        }

        foreach (var serviceImport in pendingImportServices)
        {
            if (serviceImport.Account == null)
                continue;

            if (!accountLookup.TryGetValue(serviceImport.AccountName, out var importedAccount))
            {
                errors?.Add(new InvalidOperationException(
                    $"\"{serviceImport.AccountName}\" account not defined for service import"));
                continue;
            }

            var targetSubject = string.IsNullOrEmpty(serviceImport.To)
                ? serviceImport.Subject
                : serviceImport.To;

            serviceImport.Account.Imports.Services ??= new Dictionary<string, List<ServiceImportEntry>>(StringComparer.Ordinal);
            if (!serviceImport.Account.Imports.Services.TryGetValue(targetSubject, out var importsForSubject))
            {
                importsForSubject = [];
                serviceImport.Account.Imports.Services[targetSubject] = importsForSubject;
            }

            importsForSubject.Add(new ServiceImportEntry
            {
                Account = importedAccount,
                From = serviceImport.Subject,
                To = targetSubject,
                Share = serviceImport.Share,
            });
        }

        return null;
    }

    /// <summary>
    /// Parses account exports list.
    /// Mirrors <c>parseAccountExports</c> in opts.go.
    /// </summary>
    public static (List<AccountExportConfig> Streams, List<AccountExportConfig> Services, Exception? Error) ParseAccountExports(
        object? value,
        Account account,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(account);
        if (!TryGetArray(value, out var exportArray))
        {
            return ([], [], new InvalidOperationException(
                $"Exports should be an array, got {value?.GetType().Name ?? "null"}"));
        }

        var streamExports = new List<AccountExportConfig>();
        var serviceExports = new List<AccountExportConfig>();
        foreach (var exportValue in exportArray)
        {
            var (stream, service, parseError) = ParseExportStreamOrService(exportValue, errors);
            if (parseError != null)
            {
                errors?.Add(parseError);
                continue;
            }

            if (stream != null)
            {
                stream.Account = account;
                streamExports.Add(stream);
            }

            if (service != null)
            {
                service.Account = account;
                serviceExports.Add(service);
            }
        }

        return (streamExports, serviceExports, null);
    }

    /// <summary>
    /// Parses account imports list.
    /// Mirrors <c>parseAccountImports</c> in opts.go.
    /// </summary>
    public static (List<AccountImportStreamConfig> Streams, List<AccountImportServiceConfig> Services, Exception? Error) ParseAccountImports(
        object? value,
        Account account,
        ICollection<Exception>? errors = null)
    {
        ArgumentNullException.ThrowIfNull(account);
        if (!TryGetArray(value, out var importArray))
        {
            return ([], [], new InvalidOperationException(
                $"Imports should be an array, got {value?.GetType().Name ?? "null"}"));
        }

        var streamImports = new List<AccountImportStreamConfig>();
        var serviceImports = new List<AccountImportServiceConfig>();
        var serviceSubjects = new Dictionary<string, HashSet<string>>(StringComparer.Ordinal);

        foreach (var importValue in importArray)
        {
            var (stream, service, parseError) = ParseImportStreamOrService(importValue, errors);
            if (parseError != null)
            {
                errors?.Add(parseError);
                continue;
            }

            if (service != null)
            {
                var targetSubject = string.IsNullOrEmpty(service.To) ? service.Subject : service.To;
                if (!serviceSubjects.TryGetValue(targetSubject, out var seenAccounts))
                {
                    seenAccounts = new HashSet<string>(StringComparer.Ordinal);
                    serviceSubjects[targetSubject] = seenAccounts;
                }

                if (!seenAccounts.Add(service.AccountName))
                {
                    errors?.Add(new InvalidOperationException(
                        $"Duplicate service import subject \"{targetSubject}\", previously used in import for account \"{service.AccountName}\""));
                    continue;
                }

                service.Account = account;
                serviceImports.Add(service);
            }

            if (stream != null)
            {
                stream.Account = account;
                streamImports.Add(stream);
            }
        }

        return (streamImports, serviceImports, null);
    }

    /// <summary>
    /// Parses account descriptor maps used inside import entries.
    /// Mirrors <c>parseAccount</c> in opts.go.
    /// </summary>
    public static (string AccountName, string Subject, Exception? Error) ParseAccount(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (string.Empty, string.Empty, new InvalidOperationException(
                $"Expected account descriptor map, got {value?.GetType().Name ?? "null"}"));
        }

        var accountName = string.Empty;
        var subject = string.Empty;
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "account":
                    accountName = entry as string ?? string.Empty;
                    break;
                case "subject":
                    subject = entry as string ?? string.Empty;
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return (accountName, subject, null);
    }

    /// <summary>
    /// Parses a single export entry (<c>stream</c> or <c>service</c>).
    /// Mirrors <c>parseExportStreamOrService</c> in opts.go.
    /// </summary>
    public static (AccountExportConfig? Stream, AccountExportConfig? Service, Exception? Error) ParseExportStreamOrService(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (null, null, new InvalidOperationException(
                $"Export items should be a map with type entry, got {value?.GetType().Name ?? "null"}"));
        }

        AccountExportConfig? stream = null;
        AccountExportConfig? service = null;
        var accountNames = new List<string>();
        var responseType = ServiceRespType.Singleton;
        var responseTypeSeen = false;
        var responseThreshold = TimeSpan.Zero;
        var thresholdSeen = false;
        object? latency = null;
        uint accountTokenPosition = 0;
        var allowTraceSeen = false;
        var allowTrace = false;

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "stream":
                {
                    if (service != null)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Detected stream \"{entry}\" but already saw a service"));
                        break;
                    }

                    var subject = entry as string;
                    if (string.IsNullOrEmpty(subject))
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Expected stream name to be string, got {entry?.GetType().Name ?? "null"}"));
                        break;
                    }

                    stream = new AccountExportConfig
                    {
                        Subject = subject,
                        AccountNames = [.. accountNames],
                    };
                    break;
                }
                case "service":
                {
                    if (stream != null)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Detected service \"{entry}\" but already saw a stream"));
                        break;
                    }

                    var subject = entry as string;
                    if (string.IsNullOrEmpty(subject))
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Expected service name to be string, got {entry?.GetType().Name ?? "null"}"));
                        break;
                    }

                    service = new AccountExportConfig
                    {
                        Subject = subject,
                        AccountNames = [.. accountNames],
                        ResponseType = responseType,
                        Latency = latency,
                        ResponseThreshold = responseThreshold,
                        AllowTrace = allowTraceSeen && allowTrace,
                    };
                    break;
                }
                case "response":
                case "response_type":
                {
                    if (responseTypeSeen)
                    {
                        errors?.Add(new InvalidOperationException("Duplicate response type definition"));
                        break;
                    }

                    responseTypeSeen = true;
                    var responseString = (entry as string ?? string.Empty).ToLowerInvariant();
                    var responseTypeParsed = responseString switch
                    {
                        "single" or "singleton" => ServiceRespType.Singleton,
                        "stream" => ServiceRespType.Streamed,
                        "chunk" or "chunked" => ServiceRespType.Chunked,
                        _ => (ServiceRespType?)null,
                    };
                    if (responseTypeParsed == null)
                    {
                        errors?.Add(new InvalidOperationException($"Unknown response type: \"{entry}\""));
                        break;
                    }

                    responseType = responseTypeParsed.Value;

                    if (stream != null)
                        errors?.Add(new InvalidOperationException("Detected response directive on non-service"));
                    if (service != null)
                        service.ResponseType = responseType;
                    break;
                }
                case "threshold":
                case "response_threshold":
                case "response_max_time":
                case "response_time":
                {
                    if (thresholdSeen)
                    {
                        errors?.Add(new InvalidOperationException("Duplicate response threshold detected"));
                        break;
                    }

                    thresholdSeen = true;
                    responseThreshold = ParseDuration(rawKey, entry, errors, warnings: null);
                    if (stream != null)
                        errors?.Add(new InvalidOperationException("Detected response directive on non-service"));
                    if (service != null)
                        service.ResponseThreshold = responseThreshold;
                    break;
                }
                case "accounts":
                    accountNames = ParseStringList(entry);
                    if (stream != null)
                        stream.AccountNames = [.. accountNames];
                    if (service != null)
                        service.AccountNames = [.. accountNames];
                    break;
                case "latency":
                {
                    var (parsedLatency, latencyError) = ParseServiceLatency(rawKey, entry);
                    if (latencyError != null)
                    {
                        errors?.Add(latencyError);
                        break;
                    }

                    latency = parsedLatency;
                    if (stream != null)
                    {
                        errors?.Add(new InvalidOperationException("Detected latency directive on non-service"));
                        break;
                    }

                    if (service != null)
                        service.Latency = latency;
                    break;
                }
                case "account_token_position":
                    if (TryConvertToLong(entry, out var tokenPosition))
                        accountTokenPosition = checked((uint)tokenPosition);
                    break;
                case "allow_trace":
                    allowTraceSeen = true;
                    if (TryConvertToBool(entry, out var allowTraceValue))
                        allowTrace = allowTraceValue;
                    if (stream != null)
                    {
                        errors?.Add(new InvalidOperationException("Detected allow_trace directive on non-service"));
                        break;
                    }

                    if (service != null)
                        service.AllowTrace = allowTrace;
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        if (stream != null)
            stream.AccountTokenPosition = accountTokenPosition;
        if (service != null)
            service.AccountTokenPosition = accountTokenPosition;

        return (stream, service, null);
    }

    /// <summary>
    /// Parses service-export latency configuration.
    /// Mirrors <c>parseServiceLatency</c> in opts.go.
    /// </summary>
    public static (object? Latency, Exception? Error) ParseServiceLatency(string rootField, object? value)
    {
        if (NormalizeConfigValue(value) is string subject)
        {
            return (new InternalServiceLatency
            {
                Subject = subject,
                Sampling = ServerConstants.DefaultServiceLatencySampling,
            }, null);
        }

        if (!TryGetMap(value, out var latencyMap))
        {
            return (null, new InvalidOperationException(
                $"Expected latency entry to be a map/struct or string, got {value?.GetType().Name ?? "null"}"));
        }

        var sampling = ServerConstants.DefaultServiceLatencySampling;
        if (latencyMap.TryGetValue("sampling", out var samplingRaw))
        {
            var samplingValue = NormalizeConfigValue(samplingRaw);
            var headerMode = false;
            switch (samplingValue)
            {
                case long longSampling:
                    sampling = checked((int)longSampling);
                    break;
                case string samplingString:
                {
                    if (samplingString.Trim().Equals("headers", StringComparison.OrdinalIgnoreCase))
                    {
                        headerMode = true;
                        sampling = 0;
                        break;
                    }

                    var normalizedSampling = samplingString.Trim().TrimEnd('%');
                    if (!int.TryParse(normalizedSampling, out sampling))
                    {
                        return (null, new InvalidOperationException(
                            $"Failed to parse latency sample \"{samplingString}\""));
                    }

                    break;
                }
                default:
                    return (null, new InvalidOperationException(
                        $"Expected latency sample to be a string or integer, got {samplingValue?.GetType().Name ?? "null"}"));
            }

            if (!headerMode && (sampling < 1 || sampling > 100))
                return (null, new InvalidOperationException("sampling value should be in range [1..100]"));
        }

        if (!latencyMap.TryGetValue("subject", out var subjectRaw))
        {
            return (null, new InvalidOperationException(
                $"Latency subject required in \"{rootField}\", but missing"));
        }

        var latencySubject = NormalizeConfigValue(subjectRaw) as string;
        if (string.IsNullOrWhiteSpace(latencySubject))
        {
            return (null, new InvalidOperationException(
                $"Expected latency subject to be a string, got {subjectRaw?.GetType().Name ?? "null"}"));
        }

        return (new InternalServiceLatency
        {
            Sampling = sampling,
            Subject = latencySubject,
        }, null);
    }

    /// <summary>
    /// Parses a single import entry (<c>stream</c> or <c>service</c>).
    /// Mirrors <c>parseImportStreamOrService</c> in opts.go.
    /// </summary>
    public static (AccountImportStreamConfig? Stream, AccountImportServiceConfig? Service, Exception? Error) ParseImportStreamOrService(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (null, null, new InvalidOperationException(
                $"Import items should be a map with type entry, got {value?.GetType().Name ?? "null"}"));
        }

        AccountImportStreamConfig? stream = null;
        AccountImportServiceConfig? service = null;
        var prefix = string.Empty;
        var to = string.Empty;
        var share = false;
        var allowTraceSeen = false;
        var allowTrace = false;

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "stream":
                {
                    if (service != null)
                    {
                        errors?.Add(new InvalidOperationException("Detected stream but already saw a service"));
                        break;
                    }

                    var (accountName, subject, parseError) = ParseAccount(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    if (string.IsNullOrEmpty(accountName) || string.IsNullOrEmpty(subject))
                    {
                        errors?.Add(new InvalidOperationException("Expect an account name and a subject"));
                        break;
                    }

                    stream = new AccountImportStreamConfig
                    {
                        AccountName = accountName,
                        Subject = subject,
                        Prefix = prefix,
                        To = to,
                        AllowTrace = allowTraceSeen && allowTrace,
                    };
                    break;
                }
                case "service":
                {
                    if (stream != null)
                    {
                        errors?.Add(new InvalidOperationException("Detected service but already saw a stream"));
                        break;
                    }

                    if (allowTraceSeen)
                    {
                        errors?.Add(new InvalidOperationException(
                            "Detected allow_trace directive on a non-stream"));
                        break;
                    }

                    var (accountName, subject, parseError) = ParseAccount(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    if (string.IsNullOrEmpty(accountName) || string.IsNullOrEmpty(subject))
                    {
                        errors?.Add(new InvalidOperationException("Expect an account name and a subject"));
                        break;
                    }

                    service = new AccountImportServiceConfig
                    {
                        AccountName = accountName,
                        Subject = subject,
                        To = string.IsNullOrEmpty(to) ? subject : to,
                        Share = share,
                    };
                    break;
                }
                case "prefix":
                    prefix = entry as string ?? string.Empty;
                    if (stream != null)
                        stream.Prefix = prefix;
                    break;
                case "to":
                    to = entry as string ?? string.Empty;
                    if (service != null)
                        service.To = to;
                    if (stream != null)
                    {
                        stream.To = to;
                        if (!string.IsNullOrEmpty(stream.Prefix))
                            errors?.Add(new InvalidOperationException(
                                "Stream import cannot have both 'prefix' and 'to' properties"));
                    }

                    break;
                case "share":
                    if (TryConvertToBool(entry, out var shareValue))
                        share = shareValue;
                    if (service != null)
                        service.Share = share;
                    break;
                case "allow_trace":
                    if (service != null)
                    {
                        errors?.Add(new InvalidOperationException(
                            "Detected allow_trace directive on a non-stream"));
                        break;
                    }

                    allowTraceSeen = true;
                    if (TryConvertToBool(entry, out var allowTraceValue))
                        allowTrace = allowTraceValue;
                    if (stream != null)
                        stream.AllowTrace = allowTrace;
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return (stream, service, null);
    }

    /// <summary>
    /// Applies default permissions to users and nkeys that do not have explicit permissions.
    /// Mirrors <c>applyDefaultPermissions</c> in opts.go.
    /// </summary>
    public static void ApplyDefaultPermissions(
        IReadOnlyList<User>? users,
        IReadOnlyList<NkeyUser>? nkeys,
        Permissions? defaultPermissions)
    {
        if (defaultPermissions == null)
            return;

        if (users != null)
        {
            foreach (var user in users)
            {
                user.Permissions ??= defaultPermissions;
            }
        }

        if (nkeys != null)
        {
            foreach (var user in nkeys)
            {
                user.Permissions ??= defaultPermissions;
            }
        }
    }

    /// <summary>
    /// Parses an authorization block.
    /// Mirrors <c>parseAuthorization</c> in opts.go.
    /// </summary>
    public static (ParsedAuthorizationBlock? Authorization, Exception? Error) ParseAuthorization(
        object? value,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        if (!TryGetMap(value, out var map))
            return (null, new InvalidOperationException("authorization should be a map"));

        var auth = new ParsedAuthorizationBlock();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "user":
                case "username":
                    auth.User = entry as string ?? string.Empty;
                    break;
                case "pass":
                case "password":
                    auth.Pass = entry as string ?? string.Empty;
                    break;
                case "token":
                    auth.Token = entry as string ?? string.Empty;
                    break;
                case "timeout":
                {
                    double timeoutSeconds;
                    switch (entry)
                    {
                        case long longTimeout:
                            timeoutSeconds = longTimeout;
                            break;
                        case double doubleTimeout:
                            timeoutSeconds = doubleTimeout;
                            break;
                        case string duration:
                            timeoutSeconds = ParseDuration("timeout", duration, errors, warnings).TotalSeconds;
                            break;
                        default:
                            return (null, new InvalidOperationException(
                                "error parsing authorization config, 'timeout' wrong type"));
                    }

                    auth.TimeoutSeconds = timeoutSeconds;
                    if (timeoutSeconds > TimeSpan.FromSeconds(60).TotalSeconds)
                    {
                        warnings?.Add(new InvalidOperationException(
                            $"timeout of {entry} ({timeoutSeconds} seconds) is high, consider keeping it under 60 seconds"));
                    }

                    break;
                }
                case "users":
                {
                    var (nkeys, users, parseError) = ParseUsers(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    auth.Users = users;
                    auth.Nkeys = nkeys;
                    break;
                }
                case "default_permission":
                case "default_permissions":
                case "permissions":
                    auth.DefaultPermissions = ParsePermissionsValue(entry, errors);
                    break;
                case "auth_callout":
                case "auth_hook":
                {
                    var (callout, parseError) = ParseAuthCallout(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    auth.Callout = callout;
                    break;
                }
                case "proxy_required":
                    if (TryConvertToBool(entry, out var proxyRequired))
                        auth.ProxyRequired = proxyRequired;
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        ApplyDefaultPermissions(auth.Users, auth.Nkeys, auth.DefaultPermissions);
        return (auth, null);
    }

    /// <summary>
    /// Parses users/nkeys block.
    /// Mirrors <c>parseUsers</c> in opts.go.
    /// </summary>
    public static (List<NkeyUser> Nkeys, List<User> Users, Exception? Error) ParseUsers(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetArray(value, out var usersArray))
        {
            return ([], [], new InvalidOperationException(
                $"Expected users field to be an array, got {value?.GetType().Name ?? "null"}"));
        }

        var users = new List<User>();
        var nkeys = new List<NkeyUser>();
        foreach (var userRaw in usersArray)
        {
            if (!TryGetMap(userRaw, out var userMap))
            {
                errors?.Add(new InvalidOperationException(
                    $"Expected user entry to be a map/struct, got {userRaw?.GetType().Name ?? "null"}"));
                continue;
            }

            var user = new User();
            var nkey = new NkeyUser();
            Permissions? permissions = null;
            foreach (var (rawKey, rawValue) in userMap)
            {
                var key = rawKey.ToLowerInvariant();
                var entry = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "nkey":
                        nkey.Nkey = entry as string ?? string.Empty;
                        break;
                    case "user":
                    case "username":
                        user.Username = entry as string ?? string.Empty;
                        break;
                    case "pass":
                    case "password":
                        user.Password = entry as string ?? string.Empty;
                        break;
                    case "permission":
                    case "permissions":
                    case "authorization":
                        permissions = ParsePermissionsValue(entry, errors);
                        break;
                    case "allowed_connection_types":
                    case "connection_types":
                    case "clients":
                    {
                        var connectionTypes = ParseAllowedConnectionTypes(entry, errors);
                        nkey.AllowedConnectionTypes = connectionTypes;
                        user.AllowedConnectionTypes = connectionTypes;
                        break;
                    }
                    case "proxy_required":
                        if (TryConvertToBool(entry, out var proxyRequired))
                        {
                            nkey.ProxyRequired = proxyRequired;
                            user.ProxyRequired = proxyRequired;
                        }

                        break;
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            if (permissions != null)
            {
                if (!string.IsNullOrEmpty(nkey.Nkey))
                    nkey.Permissions = permissions;
                else
                    user.Permissions = permissions;
            }

            if (string.IsNullOrEmpty(nkey.Nkey) && string.IsNullOrEmpty(user.Username))
            {
                return ([], [], new InvalidOperationException("User entry requires a user"));
            }

            if (!string.IsNullOrEmpty(nkey.Nkey))
            {
                if (!IsLikelyPublicNkey(nkey.Nkey, 'U'))
                    return ([], [], new InvalidOperationException("Not a valid public nkey for a user"));

                if (!string.IsNullOrEmpty(user.Username) || !string.IsNullOrEmpty(user.Password))
                {
                    return ([], [], new InvalidOperationException(
                        "Nkey users do not take usernames or passwords"));
                }

                nkeys.Add(nkey);
            }
            else
            {
                users.Add(user);
            }
        }

        return (nkeys, users, null);
    }

    /// <summary>
    /// Parses allowed connection types map.
    /// Mirrors <c>parseAllowedConnectionTypes</c> in opts.go.
    /// </summary>
    public static HashSet<string>? ParseAllowedConnectionTypes(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetArray(value, out var values))
        {
            errors?.Add(new InvalidOperationException(
                $"Expected allowed connection types to be an array, got {value?.GetType().Name ?? "null"}"));
            return null;
        }

        var result = new HashSet<string>(StringComparer.Ordinal);
        foreach (var item in values)
        {
            var connectionType = NormalizeConfigValue(item) as string;
            if (string.IsNullOrEmpty(connectionType))
            {
                errors?.Add(new InvalidOperationException("allowed connection type entries must be strings"));
                continue;
            }

            result.Add(connectionType);
        }

        var validateError = AuthHandler.ValidateAllowedConnectionTypes(result);
        if (validateError != null)
            errors?.Add(validateError);

        return result;
    }

    /// <summary>
    /// Parses authorization callout configuration.
    /// Mirrors <c>parseAuthCallout</c> in opts.go.
    /// </summary>
    public static (AuthCalloutOpts? Callout, Exception? Error) ParseAuthCallout(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (null, new InvalidOperationException(
                $"Expected authorization callout to be a map/struct, got {value?.GetType().Name ?? "null"}"));
        }

        var callout = new AuthCalloutOpts();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "issuer":
                    callout.Issuer = entry as string ?? string.Empty;
                    if (!IsLikelyPublicNkey(callout.Issuer, 'A'))
                    {
                        return (null, new InvalidOperationException(
                            $"Expected callout user to be a valid public account nkey, got \"{callout.Issuer}\""));
                    }

                    break;
                case "account":
                case "acc":
                    callout.Account = entry as string ?? string.Empty;
                    break;
                case "auth_users":
                case "users":
                    if (!TryGetArray(entry, out var authUsersArray))
                    {
                        return (null, new InvalidOperationException(
                            $"Expected auth_users field to be an array, got {entry?.GetType().Name ?? "null"}"));
                    }

                    foreach (var userValue in authUsersArray)
                    {
                        var authUser = NormalizeConfigValue(userValue) as string;
                        if (!string.IsNullOrEmpty(authUser))
                            callout.AuthUsers.Add(authUser);
                    }

                    break;
                case "xkey":
                case "key":
                    callout.XKey = entry as string ?? string.Empty;
                    if (!string.IsNullOrEmpty(callout.XKey) && !IsLikelyPublicNkey(callout.XKey, 'X'))
                    {
                        return (null, new InvalidOperationException(
                            $"Expected callout xkey to be a valid public xkey, got \"{callout.XKey}\""));
                    }

                    break;
                case "allowed_accounts":
                    if (!TryGetArray(entry, out var allowedAccountsArray))
                    {
                        return (null, new InvalidOperationException(
                            $"Expected allowed accounts field to be an array, got {entry?.GetType().Name ?? "null"}"));
                    }

                    foreach (var accountValue in allowedAccountsArray)
                    {
                        var accountName = NormalizeConfigValue(accountValue) as string;
                        if (!string.IsNullOrEmpty(accountName))
                            callout.AllowedAccounts.Add(accountName);
                    }

                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Unknown field \"{rawKey}\" parsing authorization callout"));
                    }

                    break;
            }
        }

        if (string.IsNullOrEmpty(callout.Account))
            callout.Account = ServerConstants.DefaultGlobalAccount;
        if (string.IsNullOrEmpty(callout.Issuer))
            return (null, new InvalidOperationException("Authorization callouts require an issuer to be specified"));
        if (callout.AuthUsers.Count == 0)
            return (null, new InvalidOperationException("Authorization callouts require authorized users to be specified"));

        return (callout, null);
    }

    // -------------------------------------------------------------------------
    // Batch 6: opts.go package-level parse/config helpers (F4)
    // -------------------------------------------------------------------------

    /// <summary>
    /// Parses user permission blocks.
    /// Mirrors <c>parseUserPermissions</c> in opts.go.
    /// </summary>
    public static (Permissions? Permissions, Exception? Error) ParseUserPermissions(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (null, new InvalidOperationException(
                $"Expected permissions to be a map/struct, got {value?.GetType().Name ?? "null"}"));
        }

        var permissions = new Permissions();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "pub":
                case "publish":
                case "import":
                {
                    var (subjectPermissions, parseError) = ParseVariablePermissions(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    permissions.Publish = subjectPermissions;
                    break;
                }
                case "sub":
                case "subscribe":
                case "export":
                {
                    var (subjectPermissions, parseError) = ParseVariablePermissions(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    permissions.Subscribe = subjectPermissions;
                    break;
                }
                case "publish_allow_responses":
                case "allow_responses":
                    if (TryConvertToBool(entry, out var responsesEnabled))
                    {
                        if (responsesEnabled)
                        {
                            permissions.Response = new ResponsePermission
                            {
                                MaxMsgs = ServerConstants.DefaultAllowResponseMaxMsgs,
                                Expires = ServerConstants.DefaultAllowResponseExpiration,
                            };
                        }
                    }
                    else
                    {
                        permissions.Response = ParseAllowResponses(entry, errors);
                    }

                    if (permissions.Response != null)
                    {
                        permissions.Publish ??= new SubjectPermission();
                        permissions.Publish.Allow ??= [];
                    }

                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Unknown field \"{rawKey}\" parsing permissions"));
                    }

                    break;
            }
        }

        AuthHandler.ValidateResponsePermissions(permissions);
        return (permissions, null);
    }

    /// <summary>
    /// Parses variable-style publish/subscribe permission values.
    /// Mirrors <c>parseVariablePermissions</c> in opts.go.
    /// </summary>
    public static (SubjectPermission? Permissions, Exception? Error) ParseVariablePermissions(
        object? value,
        ICollection<Exception>? errors = null)
    {
        return TryGetMap(value, out _)
            ? ParseSubjectPermission(value, errors)
            : ParseOldPermissionStyle(value, errors);
    }

    /// <summary>
    /// Parses single or array subject values used in permissions.
    /// Mirrors <c>parsePermSubjects</c> in opts.go.
    /// </summary>
    public static (List<string>? Subjects, Exception? Error) ParsePermSubjects(
        object? value,
        ICollection<Exception>? errors = null)
    {
        var normalized = NormalizeConfigValue(value);
        var subjects = new List<string>();

        switch (normalized)
        {
            case string single:
                subjects.Add(single);
                break;
            case IEnumerable<object?> array:
                foreach (var entry in array)
                {
                    var subject = NormalizeConfigValue(entry) as string;
                    if (subject == null)
                    {
                        return (null, new InvalidOperationException(
                            "Subject in permissions array cannot be cast to string"));
                    }

                    subjects.Add(subject);
                }

                break;
            default:
                return (null, new InvalidOperationException(
                    $"Expected subject permissions to be a subject, or array of subjects, got {normalized?.GetType().Name ?? "null"}"));
        }

        var validateError = CheckPermSubjectArray(subjects);
        if (validateError != null)
            return (null, validateError);

        return (subjects, null);
    }

    /// <summary>
    /// Parses response permissions.
    /// Mirrors <c>parseAllowResponses</c> in opts.go.
    /// </summary>
    public static ResponsePermission? ParseAllowResponses(
        object? value,
        ICollection<Exception>? errors = null)
    {
        var normalized = NormalizeConfigValue(value);
        if (TryConvertToBool(normalized, out var enabled))
        {
            return enabled
                ? new ResponsePermission
                {
                    MaxMsgs = ServerConstants.DefaultAllowResponseMaxMsgs,
                    Expires = ServerConstants.DefaultAllowResponseExpiration,
                }
                : null;
        }

        if (!TryGetMap(normalized, out var map))
        {
            errors?.Add(new InvalidOperationException(
                "error parsing response permissions, expected a boolean or a map"));
            return null;
        }

        var responsePermission = new ResponsePermission
        {
            MaxMsgs = ServerConstants.DefaultAllowResponseMaxMsgs,
            Expires = ServerConstants.DefaultAllowResponseExpiration,
        };

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "max":
                case "max_msgs":
                case "max_messages":
                case "max_responses":
                    if (!TryConvertToLong(entry, out var maxMessages))
                    {
                        errors?.Add(new InvalidOperationException("error parsing max responses"));
                        break;
                    }

                    if (maxMessages != 0)
                        responsePermission.MaxMsgs = checked((int)maxMessages);
                    break;
                case "expires":
                case "expiration":
                case "ttl":
                {
                    var ttl = ParseDuration("expires", entry, errors, warnings: null);
                    if (ttl != TimeSpan.Zero)
                        responsePermission.Expires = ttl;
                    break;
                }
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Unknown field \"{rawKey}\" parsing permissions"));
                    }

                    break;
            }
        }

        return responsePermission;
    }

    /// <summary>
    /// Parses old-style allow-only permission syntax.
    /// Mirrors <c>parseOldPermissionStyle</c> in opts.go.
    /// </summary>
    public static (SubjectPermission? Permissions, Exception? Error) ParseOldPermissionStyle(
        object? value,
        ICollection<Exception>? errors = null)
    {
        var (subjects, parseError) = ParsePermSubjects(value, errors);
        if (parseError != null)
            return (null, parseError);

        return (new SubjectPermission { Allow = subjects }, null);
    }

    /// <summary>
    /// Parses new-style allow/deny subject permissions.
    /// Mirrors <c>parseSubjectPermission</c> in opts.go.
    /// </summary>
    public static (SubjectPermission? Permissions, Exception? Error) ParseSubjectPermission(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (null, new InvalidOperationException(
                $"Expected subject permission map, got {value?.GetType().Name ?? "null"}"));
        }

        if (map.Count == 0)
            return (null, null);

        var permission = new SubjectPermission();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "allow":
                {
                    var (subjects, parseError) = ParsePermSubjects(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    permission.Allow = subjects;
                    break;
                }
                case "deny":
                {
                    var (subjects, parseError) = ParsePermSubjects(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    permission.Deny = subjects;
                    break;
                }
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"Unknown field name \"{rawKey}\" parsing subject permissions, only 'allow' or 'deny' are permitted"));
                    }

                    break;
            }
        }

        return (permission, null);
    }

    /// <summary>
    /// Validates permission subjects.
    /// Mirrors <c>checkPermSubjectArray</c> in opts.go.
    /// </summary>
    public static Exception? CheckPermSubjectArray(IReadOnlyList<string> subjects)
    {
        foreach (var subject in subjects)
        {
            if (SubscriptionIndex.IsValidSubject(subject))
                continue;

            var parts = subject.Split(' ', StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length != 2)
                return new InvalidOperationException($"subject \"{subject}\" is not a valid subject");
            if (!SubscriptionIndex.IsValidSubject(parts[0]))
                return new InvalidOperationException($"subject \"{parts[0]}\" is not a valid subject");
        }

        return null;
    }

    /// <summary>
    /// Prints TLS help text.
    /// Mirrors <c>PrintTLSHelpAndDie</c> in opts.go.
    /// </summary>
    public static void PrintTLSHelpAndDie()
    {
        Console.WriteLine("TLS configuration help");
        Console.WriteLine("Available cipher suites include:");
        foreach (var cipher in CipherSuites.CipherMap.Keys.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
            Console.WriteLine($"    {cipher}");

        Console.WriteLine();
        Console.WriteLine("Available curve preferences include:");
        foreach (var curve in CipherSuites.CurvePreferenceMap.Keys.OrderBy(x => x, StringComparer.OrdinalIgnoreCase))
            Console.WriteLine($"    {curve}");
    }

    /// <summary>
    /// Parses a configured cipher-suite name.
    /// Mirrors <c>parseCipher</c> in opts.go.
    /// </summary>
    public static (TlsCipherSuite? Cipher, Exception? Error) ParseCipher(string cipherName)
    {
        if (!CipherSuites.CipherMap.TryGetValue(cipherName, out var cipher))
            return (null, new InvalidOperationException($"unrecognized cipher {cipherName}"));

        return (cipher, null);
    }

    /// <summary>
    /// Parses a configured curve-preference name.
    /// Mirrors <c>parseCurvePreferences</c> in opts.go.
    /// </summary>
    public static (SslApplicationProtocol? Curve, Exception? Error) ParseCurvePreferences(string curveName)
    {
        if (!CipherSuites.CurvePreferenceMap.TryGetValue(curveName, out var curve))
            return (null, new InvalidOperationException($"unrecognized curve preference {curveName}"));

        return (curve, null);
    }

    /// <summary>
    /// Parses minimum TLS version config value.
    /// Mirrors <c>parseTLSVersion</c> in opts.go.
    /// </summary>
    public static (SslProtocols Version, Exception? Error) ParseTLSVersion(object? value)
    {
        if (NormalizeConfigValue(value) is not string versionText)
            return (SslProtocols.None, new InvalidOperationException($"'min_version' wrong type: {value}"));

        SslProtocols minVersion;
        try
        {
            minVersion = TlsVersionJsonConverter.Parse(versionText);
        }
        catch (Exception ex)
        {
            return (SslProtocols.None, ex);
        }

        if (minVersion != SslProtocols.Tls12 && minVersion != SslProtocols.Tls13)
        {
            return (SslProtocols.None, new InvalidOperationException(
                $"unsupported TLS version: {versionText}"));
        }

        return (minVersion, null);
    }

    /// <summary>
    /// Parses TLS config options from map values.
    /// Mirrors <c>parseTLS</c> in opts.go.
    /// </summary>
    public static (TlsConfigOpts? Options, Exception? Error) ParseTLS(object? value, bool isClientCtx)
    {
        if (!TryGetMap(value, out var map))
            return (null, new InvalidOperationException("TLS options should be a map"));

        var tlsOptions = new TlsConfigOpts();
        var insecureConfigured = new List<string>();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "cert_file":
                    tlsOptions.CertFile = entry as string ?? string.Empty;
                    break;
                case "key_file":
                    tlsOptions.KeyFile = entry as string ?? string.Empty;
                    break;
                case "ca_file":
                    tlsOptions.CaFile = entry as string ?? string.Empty;
                    break;
                case "insecure":
                    if (!TryConvertToBool(entry, out var insecure))
                        return (null, new InvalidOperationException("error parsing tls config, expected 'insecure' to be a boolean"));
                    tlsOptions.Insecure = insecure;
                    break;
                case "verify":
                    if (!TryConvertToBool(entry, out var verify))
                        return (null, new InvalidOperationException("error parsing tls config, expected 'verify' to be a boolean"));
                    tlsOptions.Verify = verify;
                    break;
                case "verify_and_map":
                    if (!TryConvertToBool(entry, out var verifyAndMap))
                        return (null, new InvalidOperationException("error parsing tls config, expected 'verify_and_map' to be a boolean"));
                    if (verifyAndMap)
                        tlsOptions.Verify = true;
                    tlsOptions.Map = verifyAndMap;
                    break;
                case "verify_cert_and_check_known_urls":
                    if (!TryConvertToBool(entry, out var verifyKnownUrls))
                    {
                        return (null, new InvalidOperationException(
                            "error parsing tls config, expected 'verify_cert_and_check_known_urls' to be a boolean"));
                    }

                    if (verifyKnownUrls && isClientCtx)
                    {
                        return (null, new InvalidOperationException(
                            "verify_cert_and_check_known_urls not supported in this context"));
                    }

                    if (verifyKnownUrls)
                        tlsOptions.Verify = true;
                    tlsOptions.TlsCheckKnownUrls = verifyKnownUrls;
                    break;
                case "allow_insecure_cipher_suites":
                    if (!TryConvertToBool(entry, out var allowInsecureCiphers))
                    {
                        return (null, new InvalidOperationException(
                            "error parsing tls config, expected 'allow_insecure_cipher_suites' to be a boolean"));
                    }

                    tlsOptions.AllowInsecureCiphers = allowInsecureCiphers;
                    break;
                case "cipher_suites":
                    if (!TryGetArray(entry, out var cipherArray) || cipherArray.Count == 0)
                    {
                        return (null, new InvalidOperationException(
                            "error parsing tls config, 'cipher_suites' cannot be empty"));
                    }

                    tlsOptions.Ciphers.Clear();
                    foreach (var cipherEntry in cipherArray)
                    {
                        if (NormalizeConfigValue(cipherEntry) is not string cipherName)
                            return (null, new InvalidOperationException("cipher suite name should be a string"));

                        var (cipher, parseError) = ParseCipher(cipherName);
                        if (parseError != null || cipher == null)
                            return (null, parseError);

                        tlsOptions.Ciphers.Add(cipher.Value);
                        if (IsLikelyInsecureCipherSuite(cipher.Value))
                            insecureConfigured.Add(cipherName);
                    }

                    break;
                case "curve_preferences":
                    if (!TryGetArray(entry, out var curveArray) || curveArray.Count == 0)
                    {
                        return (null, new InvalidOperationException(
                            "error parsing tls config, 'curve_preferences' cannot be empty"));
                    }

                    tlsOptions.CurvePreferences.Clear();
                    foreach (var curveEntry in curveArray)
                    {
                        if (NormalizeConfigValue(curveEntry) is not string curveName)
                            return (null, new InvalidOperationException("curve preference should be a string"));

                        var (curve, parseError) = ParseCurvePreferences(curveName);
                        if (parseError != null || curve == null)
                            return (null, parseError);

                        tlsOptions.CurvePreferences.Add(curve.Value);
                    }

                    break;
                case "timeout":
                    switch (entry)
                    {
                        case long timeoutLong:
                            tlsOptions.Timeout = timeoutLong;
                            break;
                        case double timeoutDouble:
                            tlsOptions.Timeout = timeoutDouble;
                            break;
                        case string timeoutString:
                            tlsOptions.Timeout = ParseDuration("tls timeout", timeoutString).TotalSeconds;
                            break;
                        default:
                            return (null, new InvalidOperationException("error parsing tls config, 'timeout' wrong type"));
                    }

                    break;
                case "connection_rate_limit":
                    if (!TryConvertToLong(entry, out var rateLimit))
                        return (null, new InvalidOperationException("error parsing tls config, 'connection_rate_limit' wrong type"));
                    tlsOptions.RateLimit = rateLimit;
                    break;
                case "pinned_certs":
                    if (!TryGetArray(entry, out var pinArray))
                    {
                        return (null, new InvalidOperationException(
                            "error parsing tls config, expected 'pinned_certs' to be a list"));
                    }

                    if (pinArray.Count > 0)
                    {
                        var pinned = new PinnedCertSet();
                        var pinRegex = new Regex("^[A-Fa-f0-9]{64}$", RegexOptions.Compiled);
                        foreach (var pinEntry in pinArray)
                        {
                            var pin = (NormalizeConfigValue(pinEntry) as string ?? string.Empty).ToLowerInvariant();
                            if (!pinRegex.IsMatch(pin))
                            {
                                return (null, new InvalidOperationException(
                                    $"error parsing tls config, 'pinned_certs' key {pin} does not look like hex-encoded sha256"));
                            }

                            pinned.Add(pin);
                        }

                        tlsOptions.PinnedCerts = pinned;
                    }

                    break;
                case "handshake_first":
                case "first":
                case "immediate":
                    switch (entry)
                    {
                        case bool handshakeFirst:
                            tlsOptions.HandshakeFirst = handshakeFirst;
                            break;
                        case string handshakeValue:
                            switch (handshakeValue.Trim().ToLowerInvariant())
                            {
                                case "true":
                                case "on":
                                    tlsOptions.HandshakeFirst = true;
                                    break;
                                case "false":
                                case "off":
                                    tlsOptions.HandshakeFirst = false;
                                    break;
                                case "auto":
                                case "auto_fallback":
                                    tlsOptions.HandshakeFirst = true;
                                    tlsOptions.FallbackDelay = ServerConstants.DefaultTlsHandshakeFirstFallbackDelay;
                                    break;
                                default:
                                {
                                    var delay = ParseDuration("handshake_first", handshakeValue);
                                    if (delay == TimeSpan.Zero)
                                    {
                                        return (null, new InvalidOperationException(
                                            $"field \"{rawKey}\" value \"{handshakeValue}\" is invalid"));
                                    }

                                    tlsOptions.HandshakeFirst = true;
                                    tlsOptions.FallbackDelay = delay;
                                    break;
                                }
                            }

                            break;
                        default:
                            return (null, new InvalidOperationException(
                                $"field \"{rawKey}\" should be a boolean or a string, got {entry?.GetType().Name ?? "null"}"));
                    }

                    break;
                case "certs":
                case "certificates":
                    if (!TryGetArray(entry, out var certsArray))
                    {
                        return (null, new InvalidOperationException(
                            $"error parsing certificates config: unsupported type {entry?.GetType().Name ?? "null"}"));
                    }

                    tlsOptions.Certificates.Clear();
                    foreach (var certEntry in certsArray)
                    {
                        if (!TryGetMap(certEntry, out var certMap))
                        {
                            return (null, new InvalidOperationException(
                                $"error parsing certificates config: unsupported type {certEntry?.GetType().Name ?? "null"}"));
                        }

                        var pair = new TlsCertPairOpt();
                        foreach (var (certKey, certValueRaw) in certMap)
                        {
                            var certValue = NormalizeConfigValue(certValueRaw) as string;
                            if (string.IsNullOrEmpty(certValue))
                            {
                                return (null, new InvalidOperationException(
                                    $"error parsing certificates config: unsupported type {certValueRaw?.GetType().Name ?? "null"}"));
                            }

                            switch (certKey)
                            {
                                case "cert_file":
                                    pair.CertFile = certValue;
                                    break;
                                case "key_file":
                                    pair.KeyFile = certValue;
                                    break;
                                default:
                                    return (null, new InvalidOperationException(
                                        $"error parsing tls certs config, unknown field \"{certKey}\""));
                            }
                        }

                        if (string.IsNullOrEmpty(pair.CertFile) || string.IsNullOrEmpty(pair.KeyFile))
                        {
                            return (null, new InvalidOperationException(
                                "error parsing certificates config: both 'cert_file' and 'key_file' options are required"));
                        }

                        tlsOptions.Certificates.Add(pair);
                    }

                    break;
                case "min_version":
                {
                    var (minVersion, parseError) = ParseTLSVersion(entry);
                    if (parseError != null)
                        return (null, new InvalidOperationException($"error parsing tls config: {parseError.Message}", parseError));
                    tlsOptions.MinVersion = minVersion;
                    break;
                }
                case "cert_match":
                    tlsOptions.CertMatch = entry as string ?? string.Empty;
                    break;
                case "cert_match_skip_invalid":
                    if (!TryConvertToBool(entry, out var certMatchSkipInvalid))
                    {
                        return (null, new InvalidOperationException(
                            "error parsing tls config, expected 'cert_match_skip_invalid' to be a boolean"));
                    }

                    tlsOptions.CertMatchSkipInvalid = certMatchSkipInvalid;
                    break;
                case "ca_certs_match":
                {
                    var (caCertsMatch, parseError) = ParseStringArray("ca_certs_match", entry, errors: null);
                    if (parseError != null || caCertsMatch == null)
                        return (null, parseError);
                    tlsOptions.CaCertsMatch = caCertsMatch;
                    break;
                }
                default:
                    return (null, new InvalidOperationException(
                        $"error parsing tls config, unknown field \"{rawKey}\""));
            }
        }

        if (tlsOptions.Certificates.Count > 0 && !string.IsNullOrEmpty(tlsOptions.CertFile))
        {
            return (null, new InvalidOperationException(
                "error parsing tls config, cannot combine 'cert_file' option with 'certs' option"));
        }

        if (tlsOptions.Ciphers.Count == 0)
            tlsOptions.Ciphers.AddRange(CipherSuites.DefaultCipherSuites());

        if (tlsOptions.CurvePreferences.Count == 0)
        {
            foreach (var curveName in CipherSuites.DefaultCurvePreferences())
            {
                if (CipherSuites.CurvePreferenceMap.TryGetValue(curveName, out var curve))
                    tlsOptions.CurvePreferences.Add(curve);
            }
        }

        if (!tlsOptions.AllowInsecureCiphers && insecureConfigured.Count > 0)
        {
            return (null, new InvalidOperationException(
                $"insecure cipher suites configured without 'allow_insecure_cipher_suites' option set: {string.Join(", ", insecureConfigured)}"));
        }

        return (tlsOptions, null);
    }

    /// <summary>
    /// Parses simple auth objects (<c>user/pass/token/timeout</c>).
    /// Mirrors <c>parseSimpleAuth</c> in opts.go.
    /// </summary>
    public static AuthorizationConfig ParseSimpleAuth(
        object? value,
        ICollection<Exception>? errors = null)
    {
        var auth = new AuthorizationConfig();
        if (!TryGetMap(value, out var map))
        {
            errors?.Add(new InvalidOperationException("authorization should be a map"));
            return auth;
        }

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "user":
                case "username":
                    auth.User = entry as string ?? string.Empty;
                    break;
                case "pass":
                case "password":
                    auth.Pass = entry as string ?? string.Empty;
                    break;
                case "token":
                    auth.Token = entry as string ?? string.Empty;
                    break;
                case "timeout":
                    if (TryConvertToDouble(entry, out var timeout))
                        auth.Timeout = timeout;
                    else
                        errors?.Add(new InvalidOperationException("error parsing authorization timeout"));
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return auth;
    }

    /// <summary>
    /// Parses string or array-of-string fields.
    /// Mirrors <c>parseStringArray</c> in opts.go.
    /// </summary>
    public static (List<string>? Values, Exception? Error) ParseStringArray(
        string fieldName,
        object? value,
        ICollection<Exception>? errors = null)
    {
        switch (NormalizeConfigValue(value))
        {
            case string text:
                return ([text], null);
            case IEnumerable<object?> array:
            {
                var values = new List<string>();
                foreach (var entry in array)
                {
                    if (NormalizeConfigValue(entry) is string item)
                    {
                        values.Add(item);
                        continue;
                    }

                    var parseError = new InvalidOperationException(
                        $"error parsing {fieldName}: unsupported type in array {entry?.GetType().Name ?? "null"}");
                    errors?.Add(parseError);
                }

                return (values, null);
            }
            default:
            {
                var parseError = new InvalidOperationException(
                    $"error parsing {fieldName}: unsupported type {value?.GetType().Name ?? "null"}");
                errors?.Add(parseError);
                return (null, parseError);
            }
        }
    }

    /// <summary>
    /// Parses websocket configuration block.
    /// Mirrors <c>parseWebsocket</c> in opts.go.
    /// </summary>
    public static Exception? ParseWebsocket(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected websocket to be a map, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "listen":
                    try
                    {
                        var (host, port) = ParseListen(entry);
                        options.Websocket.Host = host;
                        options.Websocket.Port = port;
                    }
                    catch (Exception ex)
                    {
                        errors?.Add(ex);
                    }

                    break;
                case "port":
                    if (TryConvertToLong(entry, out var websocketPort))
                        options.Websocket.Port = checked((int)websocketPort);
                    break;
                case "host":
                case "net":
                    options.Websocket.Host = entry as string ?? string.Empty;
                    break;
                case "advertise":
                    options.Websocket.Advertise = entry as string ?? string.Empty;
                    break;
                case "no_tls":
                    if (TryConvertToBool(entry, out var noTls))
                        options.Websocket.NoTls = noTls;
                    break;
                case "tls":
                {
                    var (tlsOptions, parseError) = ParseTLS(entry, isClientCtx: true);
                    if (parseError != null || tlsOptions == null)
                    {
                        errors?.Add(parseError ?? new InvalidOperationException("unable to parse websocket tls options"));
                        break;
                    }

                    var (tlsConfig, genError) = GenTLSConfig(tlsOptions);
                    if (genError != null)
                    {
                        errors?.Add(genError);
                        break;
                    }

                    options.Websocket.TlsConfig = tlsConfig;
                    options.Websocket.TlsMap = tlsOptions.Map;
                    options.Websocket.TlsPinnedCerts = tlsOptions.PinnedCerts;
                    options.Websocket.TlsConfigOpts = tlsOptions;
                    break;
                }
                case "same_origin":
                    if (TryConvertToBool(entry, out var sameOrigin))
                        options.Websocket.SameOrigin = sameOrigin;
                    break;
                case "allowed_origins":
                case "allowed_origin":
                case "allow_origins":
                case "allow_origin":
                case "origins":
                case "origin":
                {
                    var (origins, parseError) = ParseStringArray("allowed origins", entry, errors);
                    if (parseError == null && origins != null)
                        options.Websocket.AllowedOrigins = origins;
                    break;
                }
                case "handshake_timeout":
                    options.Websocket.HandshakeTimeout = ParseDuration("handshake timeout", entry, errors, warnings);
                    break;
                case "compress":
                case "compression":
                    if (TryConvertToBool(entry, out var websocketCompression))
                        options.Websocket.Compression = websocketCompression;
                    break;
                case "authorization":
                case "authentication":
                {
                    var auth = ParseSimpleAuth(entry, errors);
                    options.Websocket.Username = auth.User;
                    options.Websocket.Password = auth.Pass;
                    options.Websocket.Token = auth.Token;
                    options.Websocket.AuthTimeout = auth.Timeout;
                    break;
                }
                case "jwt_cookie":
                    options.Websocket.JwtCookie = entry as string ?? string.Empty;
                    break;
                case "user_cookie":
                    options.Websocket.UsernameCookie = entry as string ?? string.Empty;
                    break;
                case "pass_cookie":
                    options.Websocket.PasswordCookie = entry as string ?? string.Empty;
                    break;
                case "token_cookie":
                    options.Websocket.TokenCookie = entry as string ?? string.Empty;
                    break;
                case "no_auth_user":
                    options.Websocket.NoAuthUser = entry as string ?? string.Empty;
                    break;
                case "headers":
                    if (!TryGetMap(entry, out var headerMap))
                    {
                        errors?.Add(new InvalidOperationException(
                            $"error parsing headers: unsupported type {entry?.GetType().Name ?? "null"}"));
                        break;
                    }

                    var headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                    foreach (var (headerName, headerValueRaw) in headerMap)
                    {
                        if (NormalizeConfigValue(headerValueRaw) is string headerValue)
                        {
                            headers[headerName] = headerValue;
                        }
                        else
                        {
                            errors?.Add(new InvalidOperationException(
                                $"error parsing header key {headerName}: unsupported type {headerValueRaw?.GetType().Name ?? "null"}"));
                        }
                    }

                    options.Websocket.Headers = headers;
                    break;
                case "ping_interval":
                    options.Websocket.PingInterval = ParseDuration("ping_interval", entry, errors, warnings);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses MQTT configuration block.
    /// Mirrors <c>parseMQTT</c> in opts.go.
    /// </summary>
    public static Exception? ParseMQTT(
        object? value,
        ServerOptions options,
        ICollection<Exception>? errors = null,
        ICollection<Exception>? warnings = null)
    {
        ArgumentNullException.ThrowIfNull(options);

        if (!TryGetMap(value, out var map))
            return new InvalidOperationException($"Expected mqtt to be a map, got {value?.GetType().Name ?? "null"}");

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "listen":
                    try
                    {
                        var (host, port) = ParseListen(entry);
                        options.Mqtt.Host = host;
                        options.Mqtt.Port = port;
                    }
                    catch (Exception ex)
                    {
                        errors?.Add(ex);
                    }

                    break;
                case "port":
                    if (TryConvertToLong(entry, out var mqttPort))
                        options.Mqtt.Port = checked((int)mqttPort);
                    break;
                case "host":
                case "net":
                    options.Mqtt.Host = entry as string ?? string.Empty;
                    break;
                case "tls":
                {
                    var (tlsOptions, parseError) = ParseTLS(entry, isClientCtx: true);
                    if (parseError != null || tlsOptions == null)
                    {
                        errors?.Add(parseError ?? new InvalidOperationException("unable to parse mqtt tls options"));
                        break;
                    }

                    var (tlsConfig, genError) = GenTLSConfig(tlsOptions);
                    if (genError != null)
                    {
                        errors?.Add(genError);
                        break;
                    }

                    options.Mqtt.TlsConfig = tlsConfig;
                    options.Mqtt.TlsTimeout = tlsOptions.Timeout;
                    options.Mqtt.TlsMap = tlsOptions.Map;
                    options.Mqtt.TlsPinnedCerts = tlsOptions.PinnedCerts;
                    options.Mqtt.TlsConfigOpts = tlsOptions;
                    break;
                }
                case "authorization":
                case "authentication":
                {
                    var auth = ParseSimpleAuth(entry, errors);
                    options.Mqtt.Username = auth.User;
                    options.Mqtt.Password = auth.Pass;
                    options.Mqtt.Token = auth.Token;
                    options.Mqtt.AuthTimeout = auth.Timeout;
                    break;
                }
                case "no_auth_user":
                    options.Mqtt.NoAuthUser = entry as string ?? string.Empty;
                    break;
                case "ack_wait":
                case "ackwait":
                    options.Mqtt.AckWait = ParseDuration("ack_wait", entry, errors, warnings);
                    break;
                case "js_api_timeout":
                case "api_timeout":
                    options.Mqtt.JsApiTimeout = ParseDuration("js_api_timeout", entry, errors, warnings);
                    break;
                case "max_ack_pending":
                case "max_pending":
                case "max_inflight":
                    if (!TryConvertToLong(entry, out var maxAckPending))
                    {
                        errors?.Add(new InvalidOperationException("invalid max_ack_pending value"));
                        break;
                    }

                    if (maxAckPending is < 0 or > ushort.MaxValue)
                    {
                        errors?.Add(new InvalidOperationException(
                            $"invalid value {maxAckPending}, should be in [0..{ushort.MaxValue}] range"));
                        break;
                    }

                    options.Mqtt.MaxAckPending = (ushort)maxAckPending;
                    break;
                case "js_domain":
                    options.Mqtt.JsDomain = entry as string ?? string.Empty;
                    break;
                case "stream_replicas":
                    if (TryConvertToLong(entry, out var streamReplicas))
                        options.Mqtt.StreamReplicas = checked((int)streamReplicas);
                    break;
                case "consumer_replicas":
                    warnings?.Add(new InvalidOperationException(
                        "consumer replicas setting ignored in this server version"));
                    break;
                case "consumer_memory_storage":
                    if (TryConvertToBool(entry, out var consumerMemoryStorage))
                        options.Mqtt.ConsumerMemoryStorage = consumerMemoryStorage;
                    break;
                case "consumer_inactive_threshold":
                case "consumer_auto_cleanup":
                    options.Mqtt.ConsumerInactiveThreshold =
                        ParseDuration("consumer_inactive_threshold", entry, errors, warnings);
                    break;
                case "reject_qos2_publish":
                    if (TryConvertToBool(entry, out var rejectQoS2Publish))
                        options.Mqtt.RejectQoS2Pub = rejectQoS2Publish;
                    break;
                case "downgrade_qos2_subscribe":
                    if (TryConvertToBool(entry, out var downgradeQoS2Subscribe))
                        options.Mqtt.DowngradeQoS2Sub = downgradeQoS2Subscribe;
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return null;
    }

    /// <summary>
    /// Parses proxy configuration block.
    /// Mirrors <c>parseProxies</c> in opts.go.
    /// </summary>
    public static (ProxiesConfig? Proxies, Exception? Error) ParseProxies(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetMap(value, out var map))
        {
            return (null, new InvalidOperationException(
                $"expected proxies to be a map/struct, got {value?.GetType().Name ?? "null"}"));
        }

        var proxies = new ProxiesConfig();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "trusted":
                {
                    var (trusted, parseError) = ParseProxiesTrusted(entry, errors);
                    if (parseError != null)
                    {
                        errors?.Add(parseError);
                        break;
                    }

                    proxies.Trusted = trusted;
                    break;
                }
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return (proxies, null);
    }

    /// <summary>
    /// Parses trusted proxy entries.
    /// Mirrors <c>parseProxiesTrusted</c> in opts.go.
    /// </summary>
    public static (List<ProxyConfig> Trusted, Exception? Error) ParseProxiesTrusted(
        object? value,
        ICollection<Exception>? errors = null)
    {
        if (!TryGetArray(value, out var array))
        {
            return ([], new InvalidOperationException(
                $"expected proxies' trusted field to be an array, got {value?.GetType().Name ?? "null"}"));
        }

        var trusted = new List<ProxyConfig>();
        foreach (var entry in array)
        {
            if (!TryGetMap(entry, out var proxyMap))
            {
                errors?.Add(new InvalidOperationException(
                    $"expected proxies' trusted entry to be a map/struct, got {entry?.GetType().Name ?? "null"}"));
                continue;
            }

            var proxy = new ProxyConfig();
            foreach (var (rawKey, rawValue) in proxyMap)
            {
                var key = rawKey.ToLowerInvariant();
                var normalized = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "key":
                    case "public_key":
                        proxy.Key = normalized as string ?? string.Empty;
                        if (!IsValidNatsPublicKey(proxy.Key))
                        {
                            errors?.Add(new InvalidOperationException($"invalid proxy key \"{proxy.Key}\""));
                        }

                        break;
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            trusted.Add(proxy);
        }

        return (trusted, null);
    }

    /// <summary>
    /// Generates runtime TLS options from parsed TLS config.
    /// Mirrors <c>GenTLSConfig</c> in opts.go.
    /// </summary>
    public static (SslServerAuthenticationOptions? Config, Exception? Error) GenTLSConfig(TlsConfigOpts options)
    {
        ArgumentNullException.ThrowIfNull(options);

        var config = new SslServerAuthenticationOptions
        {
            EnabledSslProtocols = options.MinVersion == SslProtocols.Tls13
                ? SslProtocols.Tls13
                : SslProtocols.Tls12 | SslProtocols.Tls13,
            CertificateRevocationCheckMode = X509RevocationMode.NoCheck,
            ClientCertificateRequired = options.Verify,
        };

        if (!string.IsNullOrEmpty(options.CertFile) && string.IsNullOrEmpty(options.KeyFile))
            return (null, new InvalidOperationException("missing 'key_file' in TLS configuration"));
        if (string.IsNullOrEmpty(options.CertFile) && !string.IsNullOrEmpty(options.KeyFile))
            return (null, new InvalidOperationException("missing 'cert_file' in TLS configuration"));

        try
        {
            if (!string.IsNullOrEmpty(options.CertFile) && !string.IsNullOrEmpty(options.KeyFile))
            {
                var certificate = X509Certificate2.CreateFromPemFile(
                    ExpandPath(options.CertFile),
                    ExpandPath(options.KeyFile));
                config.ServerCertificate = new X509Certificate2(certificate.Export(X509ContentType.Pkcs12));
            }
            else if (options.Certificates.Count > 0)
            {
                var pair = options.Certificates[0];
                var certificate = X509Certificate2.CreateFromPemFile(
                    ExpandPath(pair.CertFile),
                    ExpandPath(pair.KeyFile));
                config.ServerCertificate = new X509Certificate2(certificate.Export(X509ContentType.Pkcs12));
            }
        }
        catch (Exception ex)
        {
            return (null, new InvalidOperationException($"error parsing X509 certificate/key pair: {ex.Message}", ex));
        }

        if (options.Ciphers.Count > 0)
        {
            try
            {
                config.CipherSuitesPolicy = new CipherSuitesPolicy(options.Ciphers);
            }
            catch (PlatformNotSupportedException)
            {
                // Some platforms do not allow explicit cipher suite policies.
            }
        }

        if (!string.IsNullOrEmpty(options.CaFile) && !File.Exists(ExpandPath(options.CaFile)))
            return (null, new FileNotFoundException("failed to parse root ca certificate", ExpandPath(options.CaFile)));

        return (config, null);
    }

    /// <summary>
    /// Configures options from command-line arguments.
    /// Mirrors <c>ConfigureOptions</c> in opts.go.
    /// </summary>
    public static (ServerOptions? Options, Exception? Error) ConfigureOptions(
        IReadOnlyList<string> args,
        Action? printVersion = null,
        Action? printHelp = null,
        Action? printTLSHelp = null)
    {
        var flagOptions = new ServerOptions();
        var explicitBooleans = new Dictionary<string, bool>(StringComparer.Ordinal);
        var nonFlags = new List<string>();
        string configFile = string.Empty;
        var tlsFlagsSeen = false;
        var routesFlagSeen = false;

        for (var i = 0; i < args.Count; i++)
        {
            var rawArg = args[i];
            if (!rawArg.StartsWith('-'))
            {
                nonFlags.Add(rawArg);
                continue;
            }

            var inlineValue = default(string);
            var arg = rawArg;
            var equalsIndex = rawArg.IndexOf('=');
            if (equalsIndex > 0)
            {
                arg = rawArg[..equalsIndex];
                inlineValue = rawArg[(equalsIndex + 1)..];
            }

            string? ReadValue()
            {
                if (!string.IsNullOrEmpty(inlineValue))
                    return inlineValue;
                if (i + 1 >= args.Count)
                    return null;
                i++;
                return args[i];
            }

            bool ReadBoolean(bool defaultValue = true)
            {
                var value = ReadValue();
                if (value == null || value.StartsWith('-'))
                {
                    if (value != null)
                        i--;
                    return defaultValue;
                }

                return bool.TryParse(value, out var parsed) ? parsed : defaultValue;
            }

            switch (arg)
            {
                case "-h":
                case "--help":
                    printHelp?.Invoke();
                    return (null, null);
                case "-v":
                case "--version":
                    printVersion?.Invoke();
                    return (null, null);
                case "--help_tls":
                    printTLSHelp?.Invoke();
                    return (null, null);
                case "-p":
                case "--port":
                    if (!int.TryParse(ReadValue(), out var port))
                        return (null, new InvalidOperationException("Invalid value for port"));
                    flagOptions.Port = port;
                    break;
                case "-a":
                case "--addr":
                case "--net":
                    flagOptions.Host = ReadValue() ?? string.Empty;
                    break;
                case "--client_advertise":
                    flagOptions.ClientAdvertise = ReadValue() ?? string.Empty;
                    break;
                case "-D":
                case "--debug":
                    flagOptions.Debug = ReadBoolean();
                    explicitBooleans["Debug"] = flagOptions.Debug;
                    break;
                case "-V":
                case "--trace":
                    flagOptions.Trace = ReadBoolean();
                    explicitBooleans["Trace"] = flagOptions.Trace;
                    break;
                case "-VV":
                    flagOptions.Trace = ReadBoolean();
                    flagOptions.TraceVerbose = flagOptions.Trace;
                    explicitBooleans["Trace"] = flagOptions.Trace;
                    explicitBooleans["TraceVerbose"] = flagOptions.TraceVerbose;
                    break;
                case "-DV":
                    flagOptions.Debug = ReadBoolean();
                    flagOptions.Trace = flagOptions.Debug;
                    explicitBooleans["Debug"] = flagOptions.Debug;
                    explicitBooleans["Trace"] = flagOptions.Trace;
                    break;
                case "-DVV":
                    flagOptions.Debug = ReadBoolean();
                    flagOptions.Trace = flagOptions.Debug;
                    flagOptions.TraceVerbose = flagOptions.Debug;
                    explicitBooleans["Debug"] = flagOptions.Debug;
                    explicitBooleans["Trace"] = flagOptions.Trace;
                    explicitBooleans["TraceVerbose"] = flagOptions.TraceVerbose;
                    break;
                case "-T":
                case "--logtime":
                    flagOptions.Logtime = ReadBoolean(defaultValue: true);
                    explicitBooleans["Logtime"] = flagOptions.Logtime;
                    break;
                case "--logtime_utc":
                    flagOptions.LogtimeUtc = ReadBoolean();
                    break;
                case "--user":
                    flagOptions.Username = ReadValue() ?? string.Empty;
                    break;
                case "--pass":
                    flagOptions.Password = ReadValue() ?? string.Empty;
                    break;
                case "--auth":
                    flagOptions.Authorization = ReadValue() ?? string.Empty;
                    break;
                case "-m":
                case "--http_port":
                    if (!int.TryParse(ReadValue(), out var httpPort))
                        return (null, new InvalidOperationException("Invalid value for http_port"));
                    flagOptions.HttpPort = httpPort;
                    break;
                case "--ms":
                case "--https_port":
                    if (!int.TryParse(ReadValue(), out var httpsPort))
                        return (null, new InvalidOperationException("Invalid value for https_port"));
                    flagOptions.HttpsPort = httpsPort;
                    break;
                case "-c":
                case "--config":
                    configFile = ReadValue() ?? string.Empty;
                    break;
                case "-t":
                    flagOptions.CheckConfig = ReadBoolean();
                    break;
                case "-P":
                case "--pid":
                    flagOptions.PidFile = ReadValue() ?? string.Empty;
                    break;
                case "--ports_file_dir":
                    flagOptions.PortsFileDir = ReadValue() ?? string.Empty;
                    break;
                case "-l":
                case "--log":
                    flagOptions.LogFile = ReadValue() ?? string.Empty;
                    break;
                case "--log_size_limit":
                    if (!long.TryParse(ReadValue(), out var logSizeLimit))
                        return (null, new InvalidOperationException("Invalid value for log_size_limit"));
                    flagOptions.LogSizeLimit = logSizeLimit;
                    break;
                case "-s":
                case "--syslog":
                    flagOptions.Syslog = ReadBoolean();
                    explicitBooleans["Syslog"] = flagOptions.Syslog;
                    break;
                case "-r":
                case "--remote_syslog":
                    flagOptions.RemoteSyslog = ReadValue() ?? string.Empty;
                    break;
                case "--profile":
                    if (!int.TryParse(ReadValue(), out var profilePort))
                        return (null, new InvalidOperationException("Invalid value for profile"));
                    flagOptions.ProfPort = profilePort;
                    break;
                case "--routes":
                    flagOptions.RoutesStr = ReadValue() ?? string.Empty;
                    routesFlagSeen = true;
                    break;
                case "--cluster":
                case "--cluster_listen":
                    flagOptions.Cluster.ListenStr = ReadValue() ?? string.Empty;
                    break;
                case "--cluster_advertise":
                    flagOptions.Cluster.Advertise = ReadValue() ?? string.Empty;
                    break;
                case "--no_advertise":
                    flagOptions.Cluster.NoAdvertise = ReadBoolean();
                    explicitBooleans["Cluster.NoAdvertise"] = flagOptions.Cluster.NoAdvertise;
                    break;
                case "--connect_retries":
                    if (!int.TryParse(ReadValue(), out var connectRetries))
                        return (null, new InvalidOperationException("Invalid value for connect_retries"));
                    flagOptions.Cluster.ConnectRetries = connectRetries;
                    break;
                case "--cluster_name":
                    flagOptions.Cluster.Name = ReadValue() ?? string.Empty;
                    break;
                case "--tls":
                    flagOptions.Tls = ReadBoolean();
                    tlsFlagsSeen = true;
                    break;
                case "--tlsverify":
                    flagOptions.TlsVerify = ReadBoolean();
                    tlsFlagsSeen = true;
                    break;
                case "--tlscert":
                    flagOptions.TlsCert = ReadValue() ?? string.Empty;
                    tlsFlagsSeen = true;
                    break;
                case "--tlskey":
                    flagOptions.TlsKey = ReadValue() ?? string.Empty;
                    tlsFlagsSeen = true;
                    break;
                case "--tlscacert":
                    flagOptions.TlsCaCert = ReadValue() ?? string.Empty;
                    tlsFlagsSeen = true;
                    break;
                case "--max_traced_msg_len":
                    if (!int.TryParse(ReadValue(), out var maxTraceLength))
                        return (null, new InvalidOperationException("Invalid value for max_traced_msg_len"));
                    flagOptions.MaxTracedMsgLen = maxTraceLength;
                    break;
                case "--js":
                case "--jetstream":
                    flagOptions.JetStream = ReadBoolean();
                    explicitBooleans["JetStream"] = flagOptions.JetStream;
                    break;
                case "--sd":
                case "--store_dir":
                    flagOptions.StoreDir = ReadValue() ?? string.Empty;
                    break;
                default:
                    nonFlags.Add(rawArg);
                    break;
            }
        }

        var (showVersion, showHelp, parseError) = NatsServer.ProcessCommandLineArgs(nonFlags.ToArray());
        if (parseError != null)
            return (null, parseError);
        if (showVersion)
        {
            printVersion?.Invoke();
            return (null, null);
        }

        if (showHelp)
        {
            printHelp?.Invoke();
            return (null, null);
        }

        FlagSnapshot = flagOptions.Clone();
        foreach (var (name, value) in explicitBooleans)
            TrackExplicitVal(FlagSnapshot.InCmdLine, name, value);

        ServerOptions resolvedOptions;
        if (!string.IsNullOrEmpty(configFile))
        {
            resolvedOptions = ProcessConfigFile(configFile);
            resolvedOptions = MergeOptions(resolvedOptions, flagOptions);
        }
        else
        {
            resolvedOptions = flagOptions;
        }

        if (resolvedOptions.CheckConfig && string.IsNullOrEmpty(configFile))
        {
            return (null, new InvalidOperationException(
                "must specify [-c, --config] option to check configuration file syntax"));
        }

        foreach (var (name, value) in explicitBooleans)
        {
            TrackExplicitVal(resolvedOptions.InCmdLine, name, value);
            switch (name)
            {
                case "Debug":
                    resolvedOptions.Debug = value;
                    break;
                case "Trace":
                    resolvedOptions.Trace = value;
                    break;
                case "TraceVerbose":
                    resolvedOptions.TraceVerbose = value;
                    break;
                case "Logtime":
                    resolvedOptions.Logtime = value;
                    break;
                case "Syslog":
                    resolvedOptions.Syslog = value;
                    break;
                case "Cluster.NoAdvertise":
                    resolvedOptions.Cluster.NoAdvertise = value;
                    break;
                case "JetStream":
                    resolvedOptions.JetStream = value;
                    break;
            }
        }

        if (!string.IsNullOrEmpty(resolvedOptions.Cluster.ListenStr))
        {
            var clusterError = resolvedOptions.OverrideCluster();
            if (clusterError != null)
                return (null, clusterError);
        }

        if (routesFlagSeen)
        {
            resolvedOptions.Routes = string.IsNullOrEmpty(resolvedOptions.RoutesStr)
                ? []
                : RoutesFromStr(resolvedOptions.RoutesStr);
        }

        if (tlsFlagsSeen && resolvedOptions.Tls)
        {
            var tlsError = resolvedOptions.OverrideTls();
            if (tlsError != null)
                return (null, tlsError);
        }

        if (!string.IsNullOrEmpty(resolvedOptions.RoutesStr) &&
            string.IsNullOrEmpty(resolvedOptions.Cluster.ListenStr) &&
            string.IsNullOrEmpty(resolvedOptions.Cluster.Host) &&
            resolvedOptions.Cluster.Port == 0)
        {
            return (null, new InvalidOperationException(
                "solicited routes require cluster capabilities, e.g. --cluster"));
        }

        return (resolvedOptions, null);
    }

    // -------------------------------------------------------------------------
    // Private helpers
    // -------------------------------------------------------------------------

    private static Dictionary<string, object> CreateDefaultJetStreamAccountTiers() =>
        new(StringComparer.Ordinal)
        {
            [string.Empty] = CreateUnlimitedJetStreamAccountLimits(),
        };

    private static JetStreamAccountLimits CreateUnlimitedJetStreamAccountLimits() => new()
    {
        MaxMemory = -1,
        MaxStore = -1,
        MaxStreams = -1,
        MaxConsumers = -1,
        MaxAckPending = -1,
        MemoryMaxStreamBytes = -1,
        StoreMaxStreamBytes = -1,
        MaxBytesRequired = false,
    };

    public sealed class LeafAuthorization
    {
        public string Username { get; set; } = string.Empty;
        public string Password { get; set; } = string.Empty;
        public string Nkey { get; set; } = string.Empty;
        public double TimeoutSeconds { get; set; }
        public List<User>? Users { get; set; }
        public string AccountName { get; set; } = string.Empty;
        public bool ProxyRequired { get; set; }
    }

    private static Permissions? ParsePermissionsValue(object? value, ICollection<Exception>? errors)
    {
        if (!TryGetMap(value, out var map))
        {
            errors?.Add(new InvalidOperationException(
                $"Expected permissions to be a map/struct, got {value?.GetType().Name ?? "null"}"));
            return null;
        }

        var permissions = new Permissions();
        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "publish":
                case "import":
                    permissions.Publish = ParseSubjectPermissionValue(entry, errors);
                    break;
                case "subscribe":
                case "export":
                    permissions.Subscribe = ParseSubjectPermissionValue(entry, errors);
                    break;
                case "responses":
                case "allow_responses":
                    permissions.Response = ParseAllowResponsesValue(entry, errors);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        AuthHandler.ValidateResponsePermissions(permissions);
        return permissions;
    }

    private static SubjectPermission? ParseSubjectPermissionValue(object? value, ICollection<Exception>? errors)
    {
        var normalized = NormalizeConfigValue(value);
        if (TryGetMap(normalized, out var map))
        {
            var permission = new SubjectPermission();
            foreach (var (rawKey, rawValue) in map)
            {
                var key = rawKey.ToLowerInvariant();
                var entry = NormalizeConfigValue(rawValue);
                switch (key)
                {
                    case "allow":
                        permission.Allow = ParsePermissionSubjects(entry, errors);
                        break;
                    case "deny":
                        permission.Deny = ParsePermissionSubjects(entry, errors);
                        break;
                    default:
                        if (!ConfigFlags.AllowUnknownTopLevelField)
                            errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                        break;
                }
            }

            return permission;
        }

        return new SubjectPermission
        {
            Allow = ParsePermissionSubjects(normalized, errors),
        };
    }

    private static List<string> ParsePermissionSubjects(object? value, ICollection<Exception>? errors)
    {
        if (TryGetArray(value, out var array))
        {
            var subjects = new List<string>(array.Count);
            foreach (var entry in array)
            {
                var subject = NormalizeConfigValue(entry) as string;
                if (string.IsNullOrWhiteSpace(subject))
                {
                    errors?.Add(new InvalidOperationException("permission subjects must be non-empty strings"));
                    continue;
                }

                if (!SubscriptionIndex.IsValidSubject(subject))
                {
                    errors?.Add(new InvalidOperationException($"invalid subject \"{subject}\" in permissions"));
                    continue;
                }

                subjects.Add(subject);
            }

            return subjects;
        }

        if (NormalizeConfigValue(value) is string singleSubject)
        {
            if (!SubscriptionIndex.IsValidSubject(singleSubject))
            {
                errors?.Add(new InvalidOperationException($"invalid subject \"{singleSubject}\" in permissions"));
                return [];
            }

            return [singleSubject];
        }

        errors?.Add(new InvalidOperationException(
            $"Expected permission subject array/string, got {value?.GetType().Name ?? "null"}"));
        return [];
    }

    private static ResponsePermission? ParseAllowResponsesValue(object? value, ICollection<Exception>? errors)
    {
        var normalized = NormalizeConfigValue(value);
        if (TryConvertToBool(normalized, out var enabled))
        {
            return enabled
                ? new ResponsePermission
                {
                    MaxMsgs = ServerConstants.DefaultAllowResponseMaxMsgs,
                    Expires = ServerConstants.DefaultAllowResponseExpiration,
                }
                : null;
        }

        if (!TryGetMap(normalized, out var map))
        {
            errors?.Add(new InvalidOperationException(
                $"Expected allow_responses to be a boolean or map, got {normalized?.GetType().Name ?? "null"}"));
            return null;
        }

        var response = new ResponsePermission
        {
            MaxMsgs = ServerConstants.DefaultAllowResponseMaxMsgs,
            Expires = ServerConstants.DefaultAllowResponseExpiration,
        };

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "max":
                case "max_msgs":
                    if (TryConvertToLong(entry, out var maxMessages))
                        response.MaxMsgs = checked((int)maxMessages);
                    else
                        errors?.Add(new InvalidOperationException("allow_responses.max should be an integer"));
                    break;
                case "expires":
                    response.Expires = ParseDuration("allow_responses.expires", entry, errors, warnings: null);
                    break;
                default:
                    if (!ConfigFlags.AllowUnknownTopLevelField)
                        errors?.Add(new InvalidOperationException($"unknown field \"{rawKey}\""));
                    break;
            }
        }

        return response;
    }

    private static bool IsLikelyPublicNkey(string value, char prefix) =>
        !string.IsNullOrWhiteSpace(value) &&
        value.Length >= 10 &&
        value[0] == prefix;

    private static bool IsValidNatsPublicKey(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
            return false;

        try
        {
            _ = NATS.NKeys.KeyPair.FromPublicKey(value.AsSpan());
            return true;
        }
        catch
        {
            return false;
        }
    }

    private static bool IsLikelyInsecureCipherSuite(TlsCipherSuite cipher)
    {
        var name = cipher.ToString();
        return name.Contains("_CBC_", StringComparison.OrdinalIgnoreCase) ||
               name.Contains("RC4", StringComparison.OrdinalIgnoreCase) ||
               name.Contains("3DES", StringComparison.OrdinalIgnoreCase) ||
               name.Contains("DES", StringComparison.OrdinalIgnoreCase) ||
               name.Contains("NULL", StringComparison.OrdinalIgnoreCase);
    }

    private static WriteTimeoutPolicy ParseWriteDeadlinePolicyFallback(string value, ICollection<Exception>? errors)
    {
        errors?.Add(new InvalidOperationException(
            $"write_timeout must be 'default', 'close' or 'retry' (received '{value}')"));
        return WriteTimeoutPolicy.Default;
    }

    private sealed record ParsedAuthorization(
        string Username,
        string Password,
        string Token,
        double TimeoutSeconds,
        bool HasUsers,
        bool HasCallout);

    private static ParsedAuthorization? ParseSimpleAuthorization(
        object? value,
        ICollection<Exception>? errors,
        ICollection<Exception>? warnings)
    {
        if (!TryGetMap(value, out var map))
        {
            errors?.Add(new InvalidOperationException("authorization should be a map"));
            return null;
        }

        string user = string.Empty;
        string pass = string.Empty;
        string token = string.Empty;
        double timeout = 0;
        var hasUsers = false;
        var hasCallout = false;

        foreach (var (rawKey, rawValue) in map)
        {
            var key = rawKey.ToLowerInvariant();
            var entry = NormalizeConfigValue(rawValue);
            switch (key)
            {
                case "user":
                case "username":
                    user = entry as string ?? string.Empty;
                    break;
                case "pass":
                case "password":
                    pass = entry as string ?? string.Empty;
                    break;
                case "token":
                    token = entry as string ?? string.Empty;
                    break;
                case "timeout":
                case "auth_timeout":
                    if (entry is string timeoutAsString)
                    {
                        timeout = ParseDuration("auth_timeout", timeoutAsString, errors, warnings).TotalSeconds;
                    }
                    else if (TryConvertToDouble(entry, out var timeoutSeconds))
                    {
                        timeout = timeoutSeconds;
                    }

                    break;
                case "users":
                case "nkeys":
                    hasUsers = true;
                    break;
                case "callout":
                case "auth_callout":
                    hasCallout = true;
                    break;
            }
        }

        return new ParsedAuthorization(user, pass, token, timeout, hasUsers, hasCallout);
    }

    private static bool TrySplitHostPort(string value, out string host, out int port)
    {
        host = string.Empty;
        port = 0;

        if (Uri.TryCreate($"tcp://{value}", UriKind.Absolute, out var uri))
        {
            host = uri.Host;
            if (uri.Port >= 0)
            {
                port = uri.Port;
                return true;
            }
        }

        var idx = value.LastIndexOf(':');
        if (idx <= 0 || idx >= value.Length - 1)
            return false;

        host = value[..idx];
        return int.TryParse(value[(idx + 1)..], out port);
    }

    private static bool TryGetFirst(
        IReadOnlyDictionary<string, object?> map,
        IEnumerable<string> keys,
        out object? value)
    {
        foreach (var key in keys)
        {
            if (map.TryGetValue(key, out value))
            {
                value = NormalizeConfigValue(value);
                return true;
            }
        }

        value = null;
        return false;
    }

    private static bool TryGetMap(object? value, out IReadOnlyDictionary<string, object?> map)
    {
        var normalized = NormalizeConfigValue(value);
        if (normalized is IReadOnlyDictionary<string, object?> readonlyMap)
        {
            map = readonlyMap;
            return true;
        }

        if (normalized is Dictionary<string, object?> dict)
        {
            map = dict;
            return true;
        }

        map = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
        return false;
    }

    private static bool TryGetArray(object? value, out IReadOnlyList<object?> values)
    {
        var normalized = NormalizeConfigValue(value);
        if (normalized is IReadOnlyList<object?> readonlyValues)
        {
            values = readonlyValues;
            return true;
        }

        if (normalized is List<object?> listValues)
        {
            values = listValues;
            return true;
        }

        values = [];
        return false;
    }

    private static List<string> ParseStringList(object? value)
    {
        if (TryGetArray(value, out var items))
        {
            var result = new List<string>(items.Count);
            foreach (var item in items)
            {
                var s = NormalizeConfigValue(item) as string;
                if (!string.IsNullOrEmpty(s))
                    result.Add(s);
            }

            return result;
        }

        if (NormalizeConfigValue(value) is string sValue)
            return [sValue];

        return [];
    }

    private static object? NormalizeConfigValue(object? value)
    {
        if (value is not JsonElement element)
            return value;

        return element.ValueKind switch
        {
            JsonValueKind.Object => element.EnumerateObject()
                .ToDictionary(p => p.Name, p => NormalizeConfigValue(p.Value), StringComparer.OrdinalIgnoreCase),
            JsonValueKind.Array => element.EnumerateArray()
                .Select(item => NormalizeConfigValue(item))
                .ToList(),
            JsonValueKind.String => element.GetString(),
            JsonValueKind.Number => element.TryGetInt64(out var l) ? l : element.GetDouble(),
            JsonValueKind.True => true,
            JsonValueKind.False => false,
            JsonValueKind.Null => null,
            _ => element.GetRawText(),
        };
    }

    private static bool TryConvertToLong(object? value, out long converted)
    {
        switch (NormalizeConfigValue(value))
        {
            case long longValue:
                converted = longValue;
                return true;
            case int intValue:
                converted = intValue;
                return true;
            case short shortValue:
                converted = shortValue;
                return true;
            case byte byteValue:
                converted = byteValue;
                return true;
            case double doubleValue when doubleValue >= long.MinValue && doubleValue <= long.MaxValue:
                converted = checked((long)doubleValue);
                return true;
            case float floatValue when floatValue >= long.MinValue && floatValue <= long.MaxValue:
                converted = checked((long)floatValue);
                return true;
            case string s when long.TryParse(s, out var parsed):
                converted = parsed;
                return true;
            default:
                converted = 0;
                return false;
        }
    }

    private static bool TryConvertToDouble(object? value, out double converted)
    {
        switch (NormalizeConfigValue(value))
        {
            case double d:
                converted = d;
                return true;
            case float f:
                converted = f;
                return true;
            case long l:
                converted = l;
                return true;
            case int i:
                converted = i;
                return true;
            case string s when double.TryParse(s, out var parsed):
                converted = parsed;
                return true;
            default:
                converted = 0;
                return false;
        }
    }

    private static bool TryConvertToBool(object? value, out bool converted)
    {
        switch (NormalizeConfigValue(value))
        {
            case bool b:
                converted = b;
                return true;
            case string s when bool.TryParse(s, out var parsed):
                converted = parsed;
                return true;
            default:
                converted = false;
                return false;
        }
    }

    private static string ComputeConfigDigest(string configContent)
    {
        var bytes = SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(configContent));
        return Convert.ToHexString(bytes).ToLowerInvariant();
    }

    private static void MergeRoutes(ServerOptions opts, ServerOptions flagOpts)
    {
        var routeUrls = RoutesFromStr(flagOpts.RoutesStr);
        if (routeUrls.Count == 0) return;
        opts.Routes = routeUrls;
        opts.RoutesStr = flagOpts.RoutesStr;
    }

    internal static void TrackExplicitVal(Dictionary<string, bool> pm, string name, bool val) =>
        pm[name] = val;

    private static ClusterOpts CloneClusterOpts(ClusterOpts src) => new()
    {
        Name = src.Name,
        Host = src.Host,
        Port = src.Port,
        Username = src.Username,
        Password = src.Password,
        AuthTimeout = src.AuthTimeout,
        TlsTimeout = src.TlsTimeout,
        TlsConfig = src.TlsConfig,
        TlsMap = src.TlsMap,
        TlsCheckKnownUrls = src.TlsCheckKnownUrls,
        TlsPinnedCerts = src.TlsPinnedCerts != null ? new PinnedCertSet(src.TlsPinnedCerts) : null,
        TlsHandshakeFirst = src.TlsHandshakeFirst,
        TlsHandshakeFirstFallback = src.TlsHandshakeFirstFallback,
        ListenStr = src.ListenStr,
        Advertise = src.Advertise,
        NoAdvertise = src.NoAdvertise,
        ConnectRetries = src.ConnectRetries,
        ConnectBackoff = src.ConnectBackoff,
        PoolSize = src.PoolSize,
        PinnedAccounts = [.. src.PinnedAccounts],
        Compression = new CompressionOpts { Mode = src.Compression.Mode, RttThresholds = [.. src.Compression.RttThresholds] },
        PingInterval = src.PingInterval,
        MaxPingsOut = src.MaxPingsOut,
        WriteDeadline = src.WriteDeadline,
        WriteTimeout = src.WriteTimeout,
    };

    private static GatewayOpts CloneGatewayOpts(GatewayOpts src) => new()
    {
        Name = src.Name,
        Host = src.Host,
        Port = src.Port,
        Username = src.Username,
        Password = src.Password,
        AuthTimeout = src.AuthTimeout,
        TlsConfig = src.TlsConfig,
        TlsTimeout = src.TlsTimeout,
        TlsMap = src.TlsMap,
        TlsCheckKnownUrls = src.TlsCheckKnownUrls,
        TlsPinnedCerts = src.TlsPinnedCerts != null ? new PinnedCertSet(src.TlsPinnedCerts) : null,
        Advertise = src.Advertise,
        ConnectRetries = src.ConnectRetries,
        ConnectBackoff = src.ConnectBackoff,
        Gateways = src.Gateways.Select(g => new RemoteGatewayOpts
        {
            Name = g.Name,
            TlsConfig = g.TlsConfig,
            TlsTimeout = g.TlsTimeout,
            Urls = g.Urls.Select(u => new Uri(u.ToString())).ToList(),
        }).ToList(),
        RejectUnknown = src.RejectUnknown,
        WriteDeadline = src.WriteDeadline,
        WriteTimeout = src.WriteTimeout,
    };

    private static LeafNodeOpts CloneLeafNodeOpts(LeafNodeOpts src) => new()
    {
        Host = src.Host,
        Port = src.Port,
        Username = src.Username,
        Password = src.Password,
        ProxyRequired = src.ProxyRequired,
        Nkey = src.Nkey,
        Account = src.Account,
        AuthTimeout = src.AuthTimeout,
        TlsConfig = src.TlsConfig,
        TlsTimeout = src.TlsTimeout,
        TlsMap = src.TlsMap,
        TlsPinnedCerts = src.TlsPinnedCerts != null ? new PinnedCertSet(src.TlsPinnedCerts) : null,
        TlsHandshakeFirst = src.TlsHandshakeFirst,
        TlsHandshakeFirstFallback = src.TlsHandshakeFirstFallback,
        Advertise = src.Advertise,
        NoAdvertise = src.NoAdvertise,
        ReconnectInterval = src.ReconnectInterval,
        WriteDeadline = src.WriteDeadline,
        WriteTimeout = src.WriteTimeout,
        Compression = new CompressionOpts { Mode = src.Compression.Mode, RttThresholds = [.. src.Compression.RttThresholds] },
        Remotes = src.Remotes.Select(r => new RemoteLeafOpts
        {
            LocalAccount = r.LocalAccount,
            NoRandomize = r.NoRandomize,
            Urls = r.Urls.Select(u => new Uri(u.ToString())).ToList(),
            Credentials = r.Credentials,
            Nkey = r.Nkey,
            Tls = r.Tls,
            TlsTimeout = r.TlsTimeout,
            TlsHandshakeFirst = r.TlsHandshakeFirst,
            Hub = r.Hub,
            DenyImports = [.. r.DenyImports],
            DenyExports = [.. r.DenyExports],
            FirstInfoTimeout = r.FirstInfoTimeout,
            Compression = new CompressionOpts { Mode = r.Compression.Mode, RttThresholds = [.. r.Compression.RttThresholds] },
            JetStreamClusterMigrate = r.JetStreamClusterMigrate,
            JetStreamClusterMigrateDelay = r.JetStreamClusterMigrateDelay,
            LocalIsolation = r.LocalIsolation,
            RequestIsolation = r.RequestIsolation,
            Disabled = r.Disabled,
        }).ToList(),
        MinVersion = src.MinVersion,
        IsolateLeafnodeInterest = src.IsolateLeafnodeInterest,
    };

    private static WebsocketOpts CloneWebsocketOpts(WebsocketOpts src) => new()
    {
        Host = src.Host,
        Port = src.Port,
        Advertise = src.Advertise,
        NoAuthUser = src.NoAuthUser,
        JwtCookie = src.JwtCookie,
        UsernameCookie = src.UsernameCookie,
        PasswordCookie = src.PasswordCookie,
        TokenCookie = src.TokenCookie,
        Username = src.Username,
        Password = src.Password,
        Token = src.Token,
        AuthTimeout = src.AuthTimeout,
        NoTls = src.NoTls,
        TlsConfig = src.TlsConfig,
        TlsMap = src.TlsMap,
        TlsPinnedCerts = src.TlsPinnedCerts != null ? new PinnedCertSet(src.TlsPinnedCerts) : null,
        SameOrigin = src.SameOrigin,
        AllowedOrigins = [.. src.AllowedOrigins],
        Compression = src.Compression,
        HandshakeTimeout = src.HandshakeTimeout,
        PingInterval = src.PingInterval,
        Headers = new Dictionary<string, string>(src.Headers),
    };

    private static MqttOpts CloneMqttOpts(MqttOpts src) => new()
    {
        Host = src.Host,
        Port = src.Port,
        NoAuthUser = src.NoAuthUser,
        Username = src.Username,
        Password = src.Password,
        Token = src.Token,
        JsDomain = src.JsDomain,
        StreamReplicas = src.StreamReplicas,
        ConsumerReplicas = src.ConsumerReplicas,
        ConsumerMemoryStorage = src.ConsumerMemoryStorage,
        ConsumerInactiveThreshold = src.ConsumerInactiveThreshold,
        AuthTimeout = src.AuthTimeout,
        TlsConfig = src.TlsConfig,
        TlsMap = src.TlsMap,
        TlsTimeout = src.TlsTimeout,
        TlsPinnedCerts = src.TlsPinnedCerts != null ? new PinnedCertSet(src.TlsPinnedCerts) : null,
        AckWait = src.AckWait,
        JsApiTimeout = src.JsApiTimeout,
        MaxAckPending = src.MaxAckPending,
    };
}
