using Minint.Core.Models;
using Minint.Core.Services.Impl;

namespace Minint.Tests;

public class CompositorTests
{
    private readonly Compositor _compositor = new();

    [Fact]
    public void Composite_EmptyLayer_AllTransparent()
    {
        var doc = new MinintDocument("test");
        doc.Layers.Add(new MinintLayer("L1", 4));

        uint[] result = _compositor.Composite(doc, 2, 2);

        Assert.All(result, px => Assert.Equal(0u, px));
    }

    [Fact]
    public void Composite_SingleOpaquePixel()
    {
        var doc = new MinintDocument("test");
        var red = new RgbaColor(255, 0, 0, 255);
        doc.EnsureColorCached(red);
        var layer = new MinintLayer("L1", 4);
        layer.Pixels[0] = 1;
        doc.Layers.Add(layer);

        uint[] result = _compositor.Composite(doc, 2, 2);

        // ARGB packed as 0xAARRGGBB
        uint expected = 0xFF_FF_00_00u;
        Assert.Equal(expected, result[0]);
        Assert.Equal(0u, result[1]); // rest is transparent
    }

    [Fact]
    public void Composite_HiddenLayer_Ignored()
    {
        var doc = new MinintDocument("test");
        doc.EnsureColorCached(new RgbaColor(0, 255, 0, 255));
        var layer = new MinintLayer("L1", 4);
        layer.Pixels[0] = 1;
        layer.IsVisible = false;
        doc.Layers.Add(layer);

        uint[] result = _compositor.Composite(doc, 2, 2);

        Assert.Equal(0u, result[0]);
    }

    [Fact]
    public void Composite_TwoLayers_TopOverBottom()
    {
        var doc = new MinintDocument("test");
        var red = new RgbaColor(255, 0, 0, 255);
        var blue = new RgbaColor(0, 0, 255, 255);
        int redIdx = doc.EnsureColorCached(red);
        int blueIdx = doc.EnsureColorCached(blue);

        var bottom = new MinintLayer("bottom", 1);
        bottom.Pixels[0] = redIdx;
        var top = new MinintLayer("top", 1);
        top.Pixels[0] = blueIdx;

        doc.Layers.Add(bottom);
        doc.Layers.Add(top);

        uint[] result = _compositor.Composite(doc, 1, 1);

        // Blue on top, fully opaque, should overwrite red
        Assert.Equal(0xFF_00_00_FFu, result[0]);
    }
}
