using Xunit;
using ytLive.Services;

namespace ytLive.Tests;

/// <summary>
/// TASK 4 game audio bar: the pure show/hide state machine. Show = a full-screen
/// app holds sound for half a second; hide = the app leaves fullscreen for a
/// second. Silence never hides an active bar — only the game leaving the preview
/// does (per the creator's rule).
/// </summary>
public class GameAudioHysteresisTests
{
    private static readonly DateTime T0 = new(2026, 8, 13, 12, 0, 0);

    [Fact]
    public void StaysInactive_WhileSilent()
    {
        var h = new GameAudioHysteresis();

        for (var i = 0; i < 30; i++)
        {
            h.Update(true, false, T0.AddSeconds(i));
            Assert.False(h.IsActive);
        }
    }

    [Fact]
    public void StaysInactive_UntilSoundHoldsHalfSecond()
    {
        var h = new GameAudioHysteresis();
        h.Update(true, true, T0);
        Assert.False(h.IsActive);
        h.Update(true, true, T0.AddMilliseconds(400));
        Assert.False(h.IsActive);

        h.Update(true, true, T0.AddMilliseconds(600));
        Assert.True(h.IsActive);
    }

    [Fact]
    public void NeverHides_WhileGameStillFullScreen_EvenWhenSilent()
    {
        var h = new GameAudioHysteresis();
        h.Update(true, true, T0);
        h.Update(true, true, T0.AddSeconds(1));
        Assert.True(h.IsActive);

        for (var i = 2; i < 40; i++)
        {
            h.Update(true, false, T0.AddSeconds(i));
            Assert.True(h.IsActive);
        }
    }

    [Fact]
    public void Hides_AfterAppLeavesFullScreen()
    {
        var h = new GameAudioHysteresis();
        h.Update(true, true, T0);
        h.Update(true, true, T0.AddSeconds(1));
        Assert.True(h.IsActive);

        h.Update(false, true, T0.AddSeconds(2));
        Assert.True(h.IsActive);

        h.Update(false, true, T0.AddSeconds(4));
        Assert.False(h.IsActive);
    }

    [Fact]
    public void StaysInactive_WhenNoFullScreen_EvenWithSound()
    {
        var h = new GameAudioHysteresis();

        for (var i = 0; i < 30; i++)
        {
            h.Update(false, true, T0.AddSeconds(i));
            Assert.False(h.IsActive);
        }
    }
}
