using ErsatzTV.Application.Channels;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Iptv;
using NSubstitute;
using NUnit.Framework;
using Shouldly;

namespace ErsatzTV.Core.Tests.Iptv;

[TestFixture]
public class GetChannelPlaylistHandlerTests
{
    private const string Scheme = "https";
    private const string Host = "tv.example.com";

    [Test]
    public async Task Uses_Advertised_Base_Url_When_Configured()
    {
        string m3u = await BuildM3U(configuredBaseUrl: "https://public.example.com/etv");

        m3u.ShouldContain("https://public.example.com/etv/iptv/channel/1.");
        m3u.ShouldContain("https://public.example.com/etv/iptv/xmltv.xml");
        m3u.ShouldNotContain(Host);
    }

    [Test]
    public async Task Falls_Back_To_Request_When_Unset()
    {
        string m3u = await BuildM3U(configuredBaseUrl: null);

        m3u.ShouldContain("https://tv.example.com/iptv/channel/1.");
        m3u.ShouldContain("https://tv.example.com/iptv/xmltv.xml");
        m3u.ShouldNotContain("public.example.com");
    }

    private static async Task<string> BuildM3U(string configuredBaseUrl)
    {
        var channelRepository = Substitute.For<IChannelRepository>();
        channelRepository.GetAll(Arg.Any<CancellationToken>()).Returns([BuildChannel()]);

        var configElementRepository = Substitute.For<IConfigElementRepository>();
        configElementRepository
            .GetValue<string>(Arg.Any<ConfigElementKey>(), Arg.Any<CancellationToken>())
            .Returns(Optional(configuredBaseUrl));

        var handler = new GetChannelPlaylistHandler(channelRepository, configElementRepository);

        ChannelPlaylist playlist = await handler.Handle(
            new GetChannelPlaylist(Scheme, Host, BaseUrl: "", Mode: "mixed", UserAgent: "VLC/3.0", AccessToken: null),
            CancellationToken.None);

        return playlist.ToM3U();
    }

    private static Channel BuildChannel() =>
        new(new Guid("00000000-0000-0000-0000-000000000001"))
        {
            Number = "1",
            Name = "News",
            Group = "ErsatzTV",
            IsEnabled = true,
            StreamingMode = StreamingMode.HttpLiveStreamingDirect,
            Artwork = [],
            FFmpegProfile = new FFmpegProfile
            {
                VideoFormat = FFmpegProfileVideoFormat.H264,
                AudioFormat = FFmpegProfileAudioFormat.Aac
            }
        };
}
