using Eis.Infrastructure.Authentication;

namespace Eis.Infrastructure.Tests.Authentication;

public sealed class AuthenticationStateStoreTests
{
    [Fact]
    public async Task MemoryStoreHandlesSessionsChallengesAndTotpSetups()
    {
        var options = AuthenticationOptions.CreateForTests("test-only-totp-encryption-key-32-characters");
        var state = new MemoryAuthenticationStateStore(options);

        await state.CreateSessionAsync("session-1", "user-1");
        await state.CreateSessionAsync("session-2", "user-1");
        Assert.Equal("user-1", await state.GetSessionUserIdAsync("session-1"));

        await state.CreateLoginChallengeAsync("challenge-1", "user-1");
        for (var attempt = 1; attempt <= 5; attempt++)
        {
            var failure = await state.RecordLoginChallengeFailureAsync("challenge-1", 5);
            Assert.Equal(attempt, failure?.Attempts);
        }
        Assert.Null(await state.GetLoginChallengeAsync("challenge-1"));

        await state.CreateTotpSetupAsync("session-1", "user-1", "SECRET");
        Assert.Equal(new TotpSetup("user-1", "SECRET"), await state.GetTotpSetupAsync("session-1"));
        await state.DeleteTotpSetupAsync("session-1");
        Assert.Null(await state.GetTotpSetupAsync("session-1"));

        Assert.Equal(2, await state.DeleteUserSessionsAsync("user-1"));
        Assert.Null(await state.GetSessionUserIdAsync("session-1"));
        Assert.Null(await state.GetSessionUserIdAsync("session-2"));
    }

    [Fact]
    public void RedisUrlMapsCredentialsTlsAndEndpoint()
    {
        var configuration = RedisAuthenticationStateStore.BuildConfiguration(
            "rediss://session-user:p%40ss@example.test:6380/4");
        var endpoint = Assert.Single(configuration.EndPoints);

        Assert.Equal("Unspecified/example.test:6380", endpoint.ToString());
        Assert.True(configuration.Ssl);
        Assert.Equal("example.test", configuration.SslHost);
        Assert.Equal("session-user", configuration.User);
        Assert.Equal("p@ss", configuration.Password);
    }
}
