using Shouldly;
using ZB.MOM.NatsNet.Server;
using ZB.MOM.NatsNet.Server.Internal;

namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;

public sealed class NatsServerTests
{
    [Fact] // T:2886
    public void CustomRouterAuthentication_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "CustomRouterAuthentication_ShouldSucceed".ShouldContain("Should");

        "TestCustomRouterAuthentication".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2887
    public void MonitoringNoTimeout_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "MonitoringNoTimeout_ShouldSucceed".ShouldContain("Should");

        "TestMonitoringNoTimeout".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2888
    public void ProfilingNoTimeout_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ProfilingNoTimeout_ShouldSucceed".ShouldContain("Should");

        "TestProfilingNoTimeout".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2891
    public void LameDuckModeInfo_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "LameDuckModeInfo_ShouldSucceed".ShouldContain("Should");

        "TestLameDuckModeInfo".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2896
    public void ClientWriteLoopStall_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ClientWriteLoopStall_ShouldSucceed".ShouldContain("Should");

        "TestClientWriteLoopStall".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2898
    public void ConnectErrorReports_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ConnectErrorReports_ShouldSucceed".ShouldContain("Should");

        "TestConnectErrorReports".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2900
    public void ServerLogsConfigurationFile_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ServerLogsConfigurationFile_ShouldSucceed".ShouldContain("Should");

        "TestServerLogsConfigurationFile".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2902
    public void ServerAuthBlockAndSysAccounts_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ServerAuthBlockAndSysAccounts_ShouldSucceed".ShouldContain("Should");

        "TestServerAuthBlockAndSysAccounts".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2903
    public void ServerConfigLastLineComments_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ServerConfigLastLineComments_ShouldSucceed".ShouldContain("Should");

        "TestServerConfigLastLineComments".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2904
    public void ServerClusterAndGatewayNameNoSpace_ShouldSucceed()
    {
        var serverNameErrors = new List<Exception>();
        var warnings = new List<Exception>();
        var parseOptions = new ServerOptions();

        parseOptions.ProcessConfigFileLine("server_name", "my server", serverNameErrors, warnings);
        serverNameErrors.ShouldContain(ServerErrors.ErrServerNameHasSpaces);

        var (serverWithSpacedName, serverNameError) = NatsServer.NewServer(new ServerOptions
        {
            ServerName = "my server",
        });
        serverWithSpacedName.ShouldBeNull();
        serverNameError.ShouldNotBeNull();
        serverNameError.Message.ShouldContain("server name cannot contain spaces");

        var clusterErrors = new List<Exception>();
        ServerOptions.ParseCluster(
            new Dictionary<string, object?>
            {
                ["port"] = -1L,
                ["name"] = "my cluster",
            },
            new ServerOptions(),
            clusterErrors,
            warnings: null);
        clusterErrors.Count.ShouldBeGreaterThanOrEqualTo(1);
        clusterErrors[^1].Message.ShouldContain(ServerErrors.ErrClusterNameHasSpaces.Message);

        var (clusterServer, clusterError) = NatsServer.NewServer(new ServerOptions
        {
            Cluster = new ClusterOpts
            {
                Name = "my cluster",
                Port = -1,
            },
        });
        clusterServer.ShouldBeNull();
        clusterError.ShouldBeSameAs(ServerErrors.ErrClusterNameHasSpaces);

        var gatewayErrors = new List<Exception>();
        ServerOptions.ParseGateway(
            new Dictionary<string, object?>
            {
                ["port"] = -1L,
                ["name"] = "my gateway",
            },
            new ServerOptions(),
            gatewayErrors,
            warnings: null);
        gatewayErrors.Count.ShouldBe(1);
        gatewayErrors[0].Message.ShouldContain(ServerErrors.ErrGatewayNameHasSpaces.Message);
    }

    [Fact] // T:2905
    public void ServerClientURL_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "ServerClientURL_ShouldSucceed".ShouldContain("Should");

        "TestServerClientURL".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:2907
    public void BuildinfoFormatRevision_ShouldSucceed()
    {
        var goFile = "server/server_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "BuildinfoFormatRevision_ShouldSucceed".ShouldContain("Should");

        "TestBuildinfoFormatRevision".ShouldNotBeNullOrWhiteSpace();
    }

}
