using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Domain.Filler;
using ErsatzTV.Core.Domain.Scheduling;
using ErsatzTV.Core.FFmpeg;
using ErsatzTV.Core.Interfaces.FFmpeg;
using LanguageExt;
using Microsoft.Extensions.Logging.Abstractions;
using NSubstitute;
using NUnit.Framework;
using Shouldly;

namespace ErsatzTV.Tests.Core.FFmpeg;

[TestFixture]
public class GraphicsElementSelectorTests
{
    private static (GraphicsElementSelector sel, IDecoSelector deco) Build(DecoEntries entries)
    {
        var deco = Substitute.For<IDecoSelector>();
        deco.GetDecoEntries(Arg.Any<Playout>(), Arg.Any<DateTimeOffset>()).Returns(entries);
        return (new GraphicsElementSelector(deco, NullLogger<GraphicsElementSelector>.Instance), deco);
    }

    private static Channel ChannelWithElement(int elementId, StreamingMode mode = StreamingMode.HttpLiveStreamingSegmenter)
    {
        var element = new GraphicsElement { Id = elementId, Path = "/x/on-now-next.yml", Kind = GraphicsElementKind.Text };
        return new Channel(Guid.NewGuid())
        {
            StreamingMode = mode,
            ChannelGraphicsElements = [new ChannelGraphicsElement { GraphicsElementId = elementId, GraphicsElement = element }]
        };
    }

    private static PlayoutItem Item() => new()
    {
        Playout = new Playout(),
        FillerKind = FillerKind.None,
        PlayoutItemGraphicsElements = []
    };

    [Test]
    public void Channel_Element_Is_Emitted_When_No_Deco()
    {
        (GraphicsElementSelector sel, _) = Build(new DecoEntries(Option<Deco>.None, Option<Deco>.None));

        List<PlayoutItemGraphicsElement> result = sel.SelectGraphicsElements(ChannelWithElement(7), Item(), DateTimeOffset.Now);

        result.Count.ShouldBe(1);
        result[0].GraphicsElement.Id.ShouldBe(7);
    }

    [Test]
    public void Channel_Element_Is_Suppressed_On_HlsDirect()
    {
        (GraphicsElementSelector sel, _) = Build(new DecoEntries(Option<Deco>.None, Option<Deco>.None));

        List<PlayoutItemGraphicsElement> result = sel.SelectGraphicsElements(
            ChannelWithElement(7, StreamingMode.HttpLiveStreamingDirect), Item(), DateTimeOffset.Now);

        result.ShouldBeEmpty();
    }

    [Test]
    public void Channel_Element_Is_Suppressed_By_Disable_Deco()
    {
        var deco = new Deco { GraphicsElementsMode = DecoMode.Disable, DecoGraphicsElements = [] };
        (GraphicsElementSelector sel, _) = Build(new DecoEntries(deco, Option<Deco>.None));

        List<PlayoutItemGraphicsElement> result = sel.SelectGraphicsElements(ChannelWithElement(7), Item(), DateTimeOffset.Now);

        result.ShouldBeEmpty();
    }
}
