using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Browsing;
using ZB.MOM.WW.OtOpcUa.Commons.Browsing;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Browsing;

/// <summary>Unit tests for <see cref="BrowseSessionRegistry"/>'s lookup, removal and
/// concurrent-registration behaviour.</summary>
public sealed class BrowseSessionRegistryTests
{
    [Fact]
    public void Register_then_TryGet_returns_session()
    {
        var registry = new BrowseSessionRegistry();
        var session = new FakeBrowseSession();

        registry.Register(session);
        var found = registry.TryGet(session.Token, out var got);

        found.ShouldBeTrue();
        got.ShouldBeSameAs((IBrowseSession)session);
    }

    [Fact]
    public void TryGet_unknown_returns_false()
    {
        var registry = new BrowseSessionRegistry();

        registry.TryGet(Guid.NewGuid(), out var got).ShouldBeFalse();
        got.ShouldBeNull();
    }

    [Fact]
    public void TryRemove_then_TryGet_returns_false()
    {
        var registry = new BrowseSessionRegistry();
        var session = new FakeBrowseSession();
        registry.Register(session);

        registry.TryRemove(session.Token, out var removed).ShouldBeTrue();
        removed.ShouldBeSameAs((IBrowseSession)session);
        registry.TryGet(session.Token, out _).ShouldBeFalse();
    }

    [Fact]
    public async Task Concurrent_Register_from_many_tasks_all_visible_in_Snapshot()
    {
        var registry = new BrowseSessionRegistry();
        const int count = 50;
        var sessions = Enumerable.Range(0, count).Select(_ => new FakeBrowseSession()).ToArray();

        var tasks = sessions.Select(s => Task.Run(() => registry.Register(s))).ToArray();
        await Task.WhenAll(tasks);

        var snapshot = registry.Snapshot();
        snapshot.Count.ShouldBe(count);
        var snapshotTokens = snapshot.Select(x => x.Token).OrderBy(g => g).ToArray();
        var expectedTokens = sessions.Select(s => s.Token).OrderBy(g => g).ToArray();
        snapshotTokens.ShouldBe(expectedTokens);
    }
}
