using NATS.Server.Auth;
using NATS.Server.WebSocket;

namespace NATS.Server.Transport.Tests.WebSocket;

public class WebSocketOptionsValidatorParityBatch2Tests
{
    [Fact]
    public void Validate_rejects_tls_listener_without_cert_key_when_not_no_tls()
    {
        var opts = new NatsOptions
        {
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = false,
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("TLS", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_rejects_invalid_allowed_origins()
    {
        var opts = new NatsOptions
        {
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
                AllowedOrigins = ["not-a-uri"],
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("allowed origin", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_rejects_no_auth_user_not_present_in_configured_users()
    {
        var opts = new NatsOptions
        {
            Users = [new User { Username = "alice", Password = "x" }],
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
                NoAuthUser = "bob",
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("NoAuthUser", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_rejects_username_or_token_when_users_or_nkeys_are_set()
    {
        var opts = new NatsOptions
        {
            Users = [new User { Username = "alice", Password = "x" }],
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
                Username = "ws-user",
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("users", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_rejects_jwt_cookie_without_trusted_operators()
    {
        var opts = new NatsOptions
        {
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
                JwtCookie = "jwt",
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("JwtCookie", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_rejects_reserved_response_headers_override()
    {
        var opts = new NatsOptions
        {
            TrustedKeys = ["OP1"],
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
                Headers = new Dictionary<string, string>
                {
                    ["Sec-WebSocket-Accept"] = "bad",
                },
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("reserved", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_rejects_tls_pinned_certs_when_websocket_tls_is_disabled()
    {
        var opts = new NatsOptions
        {
            TlsPinnedCerts = ["ABCDEF0123"],
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeFalse();
        result.Errors.ShouldContain(e => e.Contains("TLSPinnedCerts", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Validate_accepts_valid_minimal_configuration()
    {
        var opts = new NatsOptions
        {
            TrustedKeys = ["OP1"],
            Users = [new User { Username = "alice", Password = "x" }],
            WebSocket = new WebSocketOptions
            {
                Port = 8080,
                NoTls = true,
                NoAuthUser = "alice",
                AllowedOrigins = ["https://app.example.com"],
                JwtCookie = "jwt",
                Headers = new Dictionary<string, string>
                {
                    ["X-App-Version"] = "1",
                },
            },
        };

        var result = WebSocketOptionsValidator.Validate(opts);

        result.IsValid.ShouldBeTrue();
        result.Errors.ShouldBeEmpty();
    }
}
