using ErsatzTV.Core.FFmpeg;
using NUnit.Framework;
using Shouldly;

namespace ErsatzTV.Core.Tests.FFmpeg;

[TestFixture]
public class ColdStartFeaturesTests
{
    [Test]
    public void Should_Detect_Subtitle_BurnIn_From_Subtitles_Filter()
    {
        const string Args =
            "-i ep.mkv -filter_complex \"[0:0]subtitles=http://localhost:8409/media/subtitle/1.ass[v]\" " +
            "-c:v h264_vaapi -f hls";

        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(Args);

        features.SubtitleBurnIn.ShouldBeTrue();
    }

    [Test]
    public void Should_Not_Flag_Subtitle_BurnIn_For_Copy_Or_Overlay()
    {
        // subtitle stream copy (-c:s) and a watermark/image-subtitle overlay must NOT be read as burn-in
        const string Args = "-i ep.mkv -filter_complex \"[v][wm]overlay=10:10:format=0[vwm]\" -c:s copy -c:v libx264 -f hls";

        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(Args);

        features.SubtitleBurnIn.ShouldBeFalse();
    }

    [TestCase("-c:v h264_vaapi -f hls", "vaapi")]
    [TestCase("-c:v hevc_vaapi -f hls", "vaapi")]
    [TestCase("-c:v h264_nvenc -f hls", "nvenc")]
    [TestCase("-c:v h264_qsv -f hls", "qsv")]
    [TestCase("-c:v h264_videotoolbox -f hls", "videotoolbox")]
    [TestCase("-c:v h264_amf -f hls", "amf")]
    public void Should_Detect_Hardware_Family_From_Encoder(string args, string expected)
    {
        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(args);

        features.HardwareAcceleration.ShouldBe(expected);
    }

    [Test]
    public void Should_Detect_Hardware_Family_From_Vaapi_Filter_Even_Without_Encoder_Token()
    {
        // a vaapi-accelerated pipeline surfaces the family via filters (e.g. scale_vaapi) too
        const string Args = "-hwaccel vaapi -i ep.mkv -vf scale_vaapi=1920:1080 -f hls";

        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(Args);

        features.HardwareAcceleration.ShouldBe("vaapi");
    }

    [Test]
    public void Should_Fall_Back_To_Hwaccel_Flag_When_No_Hardware_Encoder_Or_Filter()
    {
        // hardware decode, software encode: attribute the decode accel
        const string Args = "-hwaccel cuda -i ep.mkv -c:v libx264 -f hls";

        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(Args);

        features.HardwareAcceleration.ShouldBe("cuda");
    }

    [Test]
    public void Should_Report_Software_When_No_Acceleration()
    {
        const string Args = "-i ep.mkv -c:v libx264 -c:a aac -f hls";

        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(Args);

        features.SubtitleBurnIn.ShouldBeFalse();
        features.HardwareAcceleration.ShouldBe("software");
    }

    [TestCase("")]
    [TestCase("   ")]
    [TestCase(null)]
    public void Should_Report_Unknown_For_Empty_Arguments(string args)
    {
        ColdStartFeatures features = ColdStartFeatures.FromFFmpegArguments(args);

        features.SubtitleBurnIn.ShouldBeFalse();
        features.HardwareAcceleration.ShouldBe("unknown");
    }
}
