using NATS.Server.Server;

namespace NATS.Server.Core.Tests.Server;

public class CoreServerOptionsParityBatch3Tests
{
    [Fact]
    public void Core_ports_and_compression_types_exist_with_expected_defaults()
    {
        var ports = new Ports
        {
            Nats = ["nats://127.0.0.1:4222"],
            Monitoring = ["http://127.0.0.1:8222"],
        };

        ports.Nats.ShouldHaveSingleItem();
        ports.Monitoring.ShouldHaveSingleItem();

        CompressionModes.Off.ShouldBe("off");
        CompressionModes.S2Auto.ShouldBe("s2_auto");

        var opts = new CompressionOpts();
        opts.Mode.ShouldBe(CompressionModes.Off);
        opts.RTTThresholds.ShouldNotBeNull();
    }

    [Fact]
    public void RoutesFromStr_parses_comma_delimited_routes()
    {
        var routes = NatsOptions.RoutesFromStr(" nats://a:6222, tls://b:7222 ");

        routes.Count.ShouldBe(2);
        routes[0].ToString().ShouldBe("nats://a:6222/");
        routes[1].ToString().ShouldBe("tls://b:7222/");
    }

    [Fact]
    public void Clone_returns_deep_copy_for_common_collections()
    {
        var original = new NatsOptions
        {
            Host = "127.0.0.1",
            Port = 4222,
            Tags = new Dictionary<string, string> { ["a"] = "1" },
            SubjectMappings = new Dictionary<string, string> { ["foo.*"] = "bar.$1" },
            TlsPinnedCerts = ["abc"],
        };
        original.InCmdLine.Add("host");

        var clone = original.Clone();

        clone.ShouldNotBeSameAs(original);
        clone.Tags.ShouldNotBeSameAs(original.Tags);
        clone.SubjectMappings.ShouldNotBeSameAs(original.SubjectMappings);
        clone.TlsPinnedCerts.ShouldNotBeSameAs(original.TlsPinnedCerts);
        clone.InCmdLine.ShouldNotBeSameAs(original.InCmdLine);
        clone.InCmdLine.ShouldContain("host");
    }

    [Fact]
    public void ProcessConfigString_sets_config_digest_and_applies_values()
    {
        var opts = new NatsOptions();
        opts.ProcessConfigString("port: 4333");

        opts.Port.ShouldBe(4333);
        opts.ConfigDigest().ShouldNotBeNullOrWhiteSpace();
    }

    [Fact]
    public void NoErrOnUnknownFields_toggle_is_available()
    {
        NatsOptions.NoErrOnUnknownFields(true);
        var ex = Record.Exception(() => new NatsOptions().ProcessConfigString("totally_unknown_field: 1"));
        ex.ShouldBeNull();
        NatsOptions.NoErrOnUnknownFields(false);
    }

    [Fact]
    public void Option_parity_types_exist()
    {
        var jsLimits = new JSLimitOpts
        {
            MaxRequestBatch = 10,
            MaxAckPending = 20,
        };
        jsLimits.MaxRequestBatch.ShouldBe(10);
        jsLimits.MaxAckPending.ShouldBe(20);

        var callout = new AuthCallout
        {
            Issuer = "issuer",
            Account = "A",
            AllowedAccounts = ["A", "B"],
        };
        callout.Issuer.ShouldBe("issuer");
        callout.AllowedAccounts.ShouldContain("B");

        var proxies = new ProxiesConfig
        {
            Trusted = [new ProxyConfig { Key = "k1" }],
        };
        proxies.Trusted.Count.ShouldBe(1);
        proxies.Trusted[0].Key.ShouldBe("k1");
    }
}
