using RioJoy.Core.Overlay;
using Xunit;

namespace RioJoy.Core.Tests.Overlay;

public class OverlayHitTesterTests
{
    // Two stacked cells (the chroma-split overlap case) + one disjoint cell.
    private static OverlayTemplate Template() => new()
    {
        Width = 1000,
        Height = 400,
        Regions =
        {
            new OverlayRegion { Name = "big", X = 0, Y = 0, Width = 200, Height = 100 },
            new OverlayRegion { Name = "small", X = 50, Y = 25, Width = 100, Height = 50 },
            new OverlayRegion { Name = "solo", X = 500, Y = 200, Width = 80, Height = 40 },
        },
    };

    [Fact]
    public void RegionsAt_ReturnsSmallestFirst()
    {
        IList<OverlayRegion> hits = OverlayHitTester.RegionsAt(Template(), 100, 50);

        Assert.Equal(new[] { "small", "big" }, hits.Select(r => r.Name));
    }

    [Fact]
    public void RegionsAt_MissReturnsEmpty()
    {
        Assert.Empty(OverlayHitTester.RegionsAt(Template(), 999, 399));
    }

    [Fact]
    public void RegionsAt_EdgesAreInclusiveLeftTop_ExclusiveRightBottom()
    {
        OverlayTemplate t = Template();

        Assert.Contains(OverlayHitTester.RegionsAt(t, 500, 200), r => r.Name == "solo");
        Assert.Empty(OverlayHitTester.RegionsAt(t, 580, 240)); // right/bottom edge excluded
    }

    [Fact]
    public void NextAt_FirstClickSelectsSmallest()
    {
        OverlayRegion? hit = OverlayHitTester.NextAt(Template(), 100, 50, currentName: null);

        Assert.Equal("small", hit?.Name);
    }

    [Fact]
    public void NextAt_CyclesThroughStackAndWraps()
    {
        OverlayTemplate t = Template();

        Assert.Equal("big", OverlayHitTester.NextAt(t, 100, 50, "small")?.Name);
        Assert.Equal("small", OverlayHitTester.NextAt(t, 100, 50, "big")?.Name);   // wrap
        Assert.Equal("small", OverlayHitTester.NextAt(t, 100, 50, "SOLO")?.Name);  // current not in stack
    }

    [Fact]
    public void NextAt_CurrentNameIsCaseInsensitive()
    {
        Assert.Equal("big", OverlayHitTester.NextAt(Template(), 100, 50, "SMALL")?.Name);
    }

    [Fact]
    public void NextAt_MissReturnsNull()
    {
        Assert.Null(OverlayHitTester.NextAt(Template(), 5, 395, "small"));
    }
}
