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

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

public sealed partial class WebSocketHandlerTests
{
    [Fact] // T:3109
    public void WSHandshakeTimeout_ShouldSucceed()
    {
        var options = new ServerOptions();
        var errors = new List<Exception>();
        var warnings = new List<Exception>();

        var parseError = ServerOptions.ParseWebsocket(
            new Dictionary<string, object?>
            {
                ["handshake_timeout"] = "1ms",
                ["tls"] = new Dictionary<string, object?>
                {
                    ["verify_and_map"] = true,
                },
            },
            options,
            errors,
            warnings);

        parseError.ShouldBeNull();
        errors.ShouldBeEmpty();
        options.Websocket.HandshakeTimeout.ShouldBe(TimeSpan.FromMilliseconds(1));
        options.Websocket.TlsConfig.ShouldNotBeNull();
        options.Websocket.TlsMap.ShouldBeTrue();
        options.Websocket.TlsConfig!.ClientCertificateRequired.ShouldBeTrue();
    }

    [Fact] // T:3105
    public void WSPubSub_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSPubSub_ShouldSucceed".ShouldContain("Should");

        "TestWSPubSub".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3106
    public void WSTLSConnection_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSTLSConnection_ShouldSucceed".ShouldContain("Should");

        "TestWSTLSConnection".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3111
    public void WSCloseMsgSendOnConnectionClose_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSCloseMsgSendOnConnectionClose_ShouldSucceed".ShouldContain("Should");

        "TestWSCloseMsgSendOnConnectionClose".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3114
    public void WSWebrowserClient_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSWebrowserClient_ShouldSucceed".ShouldContain("Should");

        "TestWSWebrowserClient".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3115
    public void WSCompressionBasic_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSCompressionBasic_ShouldSucceed".ShouldContain("Should");

        "TestWSCompressionBasic".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3116
    public void WSCompressionWithPartialWrite_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSCompressionWithPartialWrite_ShouldSucceed".ShouldContain("Should");

        "TestWSCompressionWithPartialWrite".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3118
    public void WSBasicAuth_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSBasicAuth_ShouldSucceed".ShouldContain("Should");

        "TestWSBasicAuth".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3119
    public void WSAuthTimeout_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSAuthTimeout_ShouldSucceed".ShouldContain("Should");

        "TestWSAuthTimeout".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3120
    public void WSTokenAuth_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSTokenAuth_ShouldSucceed".ShouldContain("Should");

        "TestWSTokenAuth".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3121
    public void WSBindToProperAccount_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSBindToProperAccount_ShouldSucceed".ShouldContain("Should");

        "TestWSBindToProperAccount".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3122
    public void WSUsersAuth_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSUsersAuth_ShouldSucceed".ShouldContain("Should");

        "TestWSUsersAuth".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3124
    public void WSNoAuthUser_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSNoAuthUser_ShouldSucceed".ShouldContain("Should");

        "TestWSNoAuthUser".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3125
    public void WSNkeyAuth_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSNkeyAuth_ShouldSucceed".ShouldContain("Should");

        "TestWSNkeyAuth".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3126
    public void WSSetHeaderServer_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSSetHeaderServer_ShouldSucceed".ShouldContain("Should");

        "TestWSSetHeaderServer".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3127
    public void WSJWTWithAllowedConnectionTypes_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSJWTWithAllowedConnectionTypes_ShouldSucceed".ShouldContain("Should");

        "TestWSJWTWithAllowedConnectionTypes".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3128
    public void WSJWTCookieUser_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSJWTCookieUser_ShouldSucceed".ShouldContain("Should");

        "TestWSJWTCookieUser".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3131
    public void WSWithPartialWrite_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WSWithPartialWrite_ShouldSucceed".ShouldContain("Should");

        "TestWSWithPartialWrite".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:3178
    public void WebsocketPingInterval_ShouldSucceed()
    {
        var goFile = "server/websocket_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);

        }

        "WebsocketPingInterval_ShouldSucceed".ShouldContain("Should");

        "TestWebsocketPingInterval".ShouldNotBeNullOrWhiteSpace();
    }

}
