using Kompas.Mcp.Core.Threading;

namespace Kompas.Mcp.Tests;

/// <summary>
/// Юнит-тесты STA-диспетчера. Запущенный КОМПАС не нужен, но нужна Windows:
/// <c>Thread.SetApartmentState(STA)</c> на Linux бросает
/// <c>PlatformNotSupportedException: COM Interop is not supported on this platform</c>.
/// Отсюда вторая метка — CI на Linux исключает тесты с <c>Requires=Windows</c>.
/// </summary>
[Trait("Category", "Unit")]
[Trait("Requires", "Windows")]
public sealed class DispatcherTests
{
    [Fact]
    public async Task Runs_work_on_STA_thread()
    {
        using var d = new KompasDispatcher();
        var state = await d.InvokeAsync(() => Thread.CurrentThread.GetApartmentState());
        Assert.Equal(ApartmentState.STA, state);
    }

    [Fact]
    public async Task Serializes_all_work_on_one_thread()
    {
        using var d = new KompasDispatcher();
        var id1 = await d.InvokeAsync(() => Environment.CurrentManagedThreadId);
        var id2 = await d.InvokeAsync(() => Environment.CurrentManagedThreadId);
        Assert.Equal(id1, id2);
        Assert.NotEqual(Environment.CurrentManagedThreadId, id1);
    }

    [Fact]
    public async Task Propagates_exceptions_to_caller()
    {
        using var d = new KompasDispatcher();
        await Assert.ThrowsAsync<InvalidOperationException>(
            () => d.InvokeAsync<int>(() => throw new InvalidOperationException("boom")));
    }

    [Fact]
    public async Task Throws_ObjectDisposed_after_dispose()
    {
        var d = new KompasDispatcher();
        d.Dispose();
        await Assert.ThrowsAsync<ObjectDisposedException>(() => d.InvokeAsync(() => { }));
    }

    [Fact]
    public async Task Nested_invoke_runs_inline_without_deadlock()
    {
        using var d = new KompasDispatcher();
        var result = await d.InvokeAsync(() =>
        {
            // Вложенный вызов на том же потоке должен выполниться синхронно, без дедлока.
            return d.InvokeAsync(() => 42).GetAwaiter().GetResult();
        });
        Assert.Equal(42, result);
    }
}
