using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Iptv;

namespace ErsatzTV.Application.Channels;

public class GetChannelPlaylistHandler(
    IChannelRepository channelRepository,
    IConfigElementRepository configElementRepository)
    : IRequestHandler<GetChannelPlaylist, ChannelPlaylist>
{
    public async Task<ChannelPlaylist> Handle(GetChannelPlaylist request, CancellationToken cancellationToken)
    {
        Option<string> maybeBaseUrl =
            await configElementRepository.GetValue<string>(ConfigElementKey.IptvBaseUrl, cancellationToken);

        (string scheme, string host, string baseUrl) = AdvertisedBaseUrl.Resolve(
            maybeBaseUrl.IfNone(string.Empty),
            request.Scheme,
            request.Host,
            request.BaseUrl);

        List<Channel> channels = EnsureMode(await channelRepository.GetAll(cancellationToken), request.Mode);
        return new ChannelPlaylist(
            scheme,
            host,
            baseUrl,
            channels,
            request.UserAgent,
            request.AccessToken);
    }

    private static List<Channel> EnsureMode(IEnumerable<Channel> channels, string mode)
    {
        var result = new List<Channel>();
        foreach (Channel channel in channels)
        {
            if (!channel.IsEnabled)
            {
                continue;
            }

            switch (mode.ToLowerInvariant())
            {
                case "segmenter":
                    channel.StreamingMode = StreamingMode.HttpLiveStreamingSegmenter;
                    result.Add(channel);
                    break;
                case "hls-direct":
                    channel.StreamingMode = StreamingMode.HttpLiveStreamingDirect;
                    result.Add(channel);
                    break;
                case "ts-legacy":
                    channel.StreamingMode = StreamingMode.TransportStream;
                    result.Add(channel);
                    break;
                case "ts":
                    channel.StreamingMode = StreamingMode.TransportStreamHybrid;
                    result.Add(channel);
                    break;
                default:
                    result.Add(channel);
                    break;
            }
        }

        return result;
    }
}
