using System;
using System.Threading;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Sta;

namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests;

[Trait("Category", "Unit")]
public sealed class StaPumpTests
{
    [Fact]
    public async Task InvokeAsync_runs_work_on_the_STA_thread()
    {
        using var pump = new StaPump();
        await pump.WaitForStartedAsync();

        var apartment = await pump.InvokeAsync(() => Thread.CurrentThread.GetApartmentState());
        apartment.ShouldBe(ApartmentState.STA);
    }

    [Fact]
    public async Task Responsiveness_probe_returns_true_under_healthy_pump()
    {
        using var pump = new StaPump();
        await pump.WaitForStartedAsync();

        (await pump.IsResponsiveAsync(TimeSpan.FromSeconds(2))).ShouldBeTrue();
    }

    [Fact]
    public async Task Responsiveness_probe_returns_false_when_pump_is_wedged()
    {
        using var pump = new StaPump();
        await pump.WaitForStartedAsync();

        // Wedge the pump with an infinite work item on the STA thread.
        var wedge = new ManualResetEventSlim();
        _ = pump.InvokeAsync(() => wedge.Wait());

        var responsive = await pump.IsResponsiveAsync(TimeSpan.FromMilliseconds(500));
        responsive.ShouldBeFalse();

        wedge.Set();
    }
}
