using System.Runtime.Versioning;
using DragonISO.Engine.NdiInterop;
using DragonISO.Engine.Pipeline;

namespace DragonISO.Engine.Tests.Interop;

// NdiInteropPInvoke is [SupportedOSPlatform("windows")]; these tests exercise
// pure helpers that never touch native code, but inherit the platform tag.
// Same pattern as NdiInteropNormalizeGroupsTests.
[SupportedOSPlatform("windows")]

// NdiPInvokeSenderHandle and NdiInteropPInvoke.BuildVideoFrame are internal;
// the engine tests project has access via InternalsVisibleTo.
public class NdiInteropSendFrameTests
{
    private static ProcessedFrame MakeFrame(int width, int height, PixelFormat format) =>
        new(width, height, 42, new byte[width * height * 4], format);

    [Fact]
    public void SenderHandle_CarriesFrameRate()
    {
        // CreateSender stashes the configured rational on the handle so SendFrame
        // can stamp every outgoing video frame without re-plumbing the settings.
        var handle = new NdiPInvokeSenderHandle(IntPtr.Zero, "Dragon-ISO_01", 30000, 1001);

        handle.FrameRateN.Should().Be(30000);
        handle.FrameRateD.Should().Be(1001);
    }

    [Fact]
    public void BuildVideoFrame_StampsConfiguredFrameRate()
    {
        var frame = MakeFrame(1280, 720, PixelFormat.Bgra);

        var native = NdiInteropPInvoke.BuildVideoFrame(frame, IntPtr.Zero, 24000, 1001);

        native.frame_rate_N.Should().Be(24000,
            because: "advertising the wrong rational causes drift and A/V desync downstream");
        native.frame_rate_D.Should().Be(1001);
    }

    [Fact]
    public void BuildVideoFrame_PreservesDimensionsAndStride()
    {
        var frame = MakeFrame(1920, 1080, PixelFormat.Bgra);

        var native = NdiInteropPInvoke.BuildVideoFrame(frame, IntPtr.Zero, 60000, 1001);

        native.xres.Should().Be(1920);
        native.yres.Should().Be(1080);
        native.line_stride_in_bytes.Should().Be(1920 * 4, because: "BGRA is 4 bytes per pixel");
    }

    [Fact]
    public void BuildVideoFrame_MapsUyvyStride()
    {
        var frame = MakeFrame(1280, 720, PixelFormat.Uyvy);

        var native = NdiInteropPInvoke.BuildVideoFrame(frame, IntPtr.Zero, 60000, 1001);

        native.line_stride_in_bytes.Should().Be(1280 * 2, because: "UYVY is 2 bytes per pixel");
    }
}
