using NATS.Client.Core;
using NATS.NKeys;

namespace NATS.E2E.Tests.Infrastructure;

public sealed class AuthServerFixture : IAsyncLifetime
{
    private NatsServerProcess _server = null!;

    public string NKeyPublicKey { get; }
    public string NKeySeed { get; }

    public int Port => _server.Port;

    public AuthServerFixture()
    {
        var kp = KeyPair.CreatePair(PrefixByte.User);
        NKeyPublicKey = kp.GetPublicKey();
        NKeySeed = kp.GetSeed();
    }

    public async Task InitializeAsync()
    {
        var config = $$"""
            max_payload: 512

            authorization {
                users: [
                    { user: "testuser", password: "testpass" },
                    {
                        user: "pubonly",
                        password: "pubpass",
                        permissions: {
                            publish: { allow: ["allowed.>"] },
                            subscribe: { allow: ["_INBOX.>"] }
                        }
                    },
                    {
                        user: "subonly",
                        password: "subpass",
                        permissions: {
                            subscribe: { allow: ["allowed.>", "_INBOX.>"] },
                            publish: { allow: ["_INBOX.>"] }
                        }
                    },
                    { user: "limited", password: "limpass" },
                    { nkey: "{{NKeyPublicKey}}" }
                ]
            }

            max_subs: 5
            """;

        _server = NatsServerProcess.WithConfig(config);
        await _server.StartAsync();
    }

    public async Task DisposeAsync()
    {
        await _server.DisposeAsync();
    }

    public NatsConnection CreateClient(string user, string password)
    {
        var opts = new NatsOpts
        {
            Url = $"nats://127.0.0.1:{Port}",
            AuthOpts = new NatsAuthOpts
            {
                Username = user,
                Password = password,
            },
        };
        return new NatsConnection(opts);
    }

    public NatsConnection CreateClient()
        => new(new NatsOpts { Url = $"nats://127.0.0.1:{Port}" });
}

[CollectionDefinition("E2E-Auth")]
public class AuthCollection : ICollectionFixture<AuthServerFixture>;
