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

namespace ErsatzTV.Tests.Application.Channels;

[TestFixture]
public class GetAllChannelsForApiHandlerTests
{
    [Test]
    public async Task Should_Project_Management_Table_Fields()
    {
        IChannelRepository repository = Substitute.For<IChannelRepository>();
        repository.GetAll(Arg.Any<CancellationToken>())
            .Returns([
                new Channel(Guid.NewGuid())
                {
                    Id = 7,
                    Number = "7.1",
                    SortNumber = 7.1,
                    Name = "Retro Cartoons",
                    Group = "Kids",
                    Categories = "animation",
                    FFmpegProfile = new FFmpegProfile { Name = "HLS 720p" },
                    PreferredAudioLanguageCode = "eng",
                    StreamingMode = StreamingMode.HttpLiveStreamingSegmenter,
                    IsEnabled = false,
                    ShowInEpg = false
                }
            ]);
        var handler = new GetAllChannelsForApiHandler(repository);

        List<ChannelResponseModel> result = await handler.Handle(
            new GetAllChannelsForApi(),
            CancellationToken.None);

        ChannelResponseModel channel = result.ShouldHaveSingleItem();
        channel.Id.ShouldBe(7);
        channel.Number.ShouldBe("7.1");
        channel.SortNumber.ShouldBe(7.1);
        channel.Name.ShouldBe("Retro Cartoons");
        channel.Group.ShouldBe("Kids");
        channel.Categories.ShouldBe("animation");
        channel.FFmpegProfile.ShouldBe("HLS 720p");
        channel.Language.ShouldBe("eng");
        channel.StreamingMode.ShouldBe("HLS Segmenter");
        channel.IsEnabled.ShouldBeFalse();
        channel.ShowInEpg.ShouldBeFalse();
        // No logo artwork -> null so the SPA renders its generated initials fallback.
        channel.Logo.ShouldBeNull();
    }

    [Test]
    public async Task Should_Root_Uploaded_Logo_Url()
    {
        IChannelRepository repository = Substitute.For<IChannelRepository>();
        repository.GetAll(Arg.Any<CancellationToken>())
            .Returns([NewChannel(new Artwork { ArtworkKind = ArtworkKind.Logo, Path = "abc123.png" })]);
        var handler = new GetAllChannelsForApiHandler(repository);

        List<ChannelResponseModel> result = await handler.Handle(
            new GetAllChannelsForApi(),
            CancellationToken.None);

        // Uploaded logos are addressed as "iptv/logos/{file}"; the browse DTO roots it (leading slash) so
        // the SPA's <img src> resolves against the site root regardless of the current SPA route.
        result.ShouldHaveSingleItem().Logo.ShouldBe("/iptv/logos/abc123.png");
    }

    [Test]
    public async Task Should_Pass_Through_External_Logo_Url()
    {
        IChannelRepository repository = Substitute.For<IChannelRepository>();
        repository.GetAll(Arg.Any<CancellationToken>())
            .Returns([NewChannel(new Artwork { ArtworkKind = ArtworkKind.Logo, Path = "https://example.com/logo.png" })]);
        var handler = new GetAllChannelsForApiHandler(repository);

        List<ChannelResponseModel> result = await handler.Handle(
            new GetAllChannelsForApi(),
            CancellationToken.None);

        // An absolute external URL is directly usable and must pass through unchanged (no leading slash added).
        result.ShouldHaveSingleItem().Logo.ShouldBe("https://example.com/logo.png");
    }

    private static Channel NewChannel(params Artwork[] artwork) =>
        new(Guid.NewGuid())
        {
            Id = 7,
            Number = "7.1",
            SortNumber = 7.1,
            Name = "Retro Cartoons",
            Group = "Kids",
            Categories = "animation",
            FFmpegProfile = new FFmpegProfile { Name = "HLS 720p" },
            PreferredAudioLanguageCode = "eng",
            StreamingMode = StreamingMode.HttpLiveStreamingSegmenter,
            IsEnabled = false,
            ShowInEpg = false,
            Artwork = [.. artwork]
        };
}
