using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;

namespace MBN_STOCK_WEBVIEW.Core.Tests;

public sealed class LegacyRefreshEpochTests
{
    [Fact]
    public void Stop_PreventsAStaleWriteFromReactivatingState()
    {
        using var cancellation = new CancellationTokenSource();
        var epoch = new LegacyRefreshEpoch<string>("idle");
        epoch.Replace(cancellation, _ => "active");

        epoch.Stop(_ => "stopped");
        var staleWriteAccepted = epoch.TryUpdate(cancellation, _ => "active-again");

        Assert.True(cancellation.IsCancellationRequested);
        Assert.False(staleWriteAccepted);
        Assert.Equal("stopped", epoch.ReadState());
    }

    [Fact]
    public void Replacement_RejectsAllWritesFromTheOldGeneration()
    {
        using var oldCancellation = new CancellationTokenSource();
        using var newCancellation = new CancellationTokenSource();
        var epoch = new LegacyRefreshEpoch<string>("idle");
        epoch.Replace(oldCancellation, _ => "old-active");

        epoch.Replace(newCancellation, _ => "new-active");
        var staleFaultAccepted = epoch.TryUpdate(oldCancellation, _ => "old-fault");
        var currentWriteAccepted = epoch.TryUpdate(newCancellation, _ => "new-scheduled");

        Assert.True(oldCancellation.IsCancellationRequested);
        Assert.False(newCancellation.IsCancellationRequested);
        Assert.False(staleFaultAccepted);
        Assert.True(currentWriteAccepted);
        Assert.Equal("new-scheduled", epoch.ReadState());
    }

    [Fact]
    public void OldCompletion_DoesNotClearOrRewriteTheReplacement()
    {
        using var oldCancellation = new CancellationTokenSource();
        using var newCancellation = new CancellationTokenSource();
        var epoch = new LegacyRefreshEpoch<string>("idle");
        epoch.Replace(oldCancellation, _ => "old-active");
        epoch.Replace(newCancellation, _ => "new-active");

        var oldCompletionAccepted = epoch.TryComplete(
            oldCancellation,
            _ => "old-complete");

        Assert.False(oldCompletionAccepted);
        Assert.True(epoch.IsCurrent(newCancellation));
        Assert.Equal("new-active", epoch.ReadState());

        Assert.True(epoch.TryComplete(newCancellation, _ => "new-complete"));
        Assert.False(epoch.IsCurrent(newCancellation));
        Assert.Equal("new-complete", epoch.ReadState());
    }
}
