using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.SRFPlay.Api;
using Microsoft.Extensions.Logging;

namespace Jellyfin.Plugin.SRFPlay.Tests
{
    public class TestPlayV3Api
    {
        public static async Task RunTests()
        {
            Console.WriteLine("=== Play v3 API Test Suite ===\n");

            using var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder.AddConsole();
                builder.SetMinimumLevel(LogLevel.Warning);
            });

            var apiClient = new SRFApiClient(loggerFactory);
            var cancellationToken = CancellationToken.None;

            // Test 1: Get all shows
            Console.WriteLine("[Test 1] Fetch All Shows");
            Console.WriteLine("------------------------");
            try
            {
                var shows = await apiClient.GetAllShowsAsync("srf", cancellationToken);
                if (shows != null && shows.Any())
                {
                    Console.WriteLine($"✓ Successfully fetched {shows.Count} shows");
                    Console.WriteLine($"  First show: {shows[0]?.Title} ({shows[0]?.NumberOfEpisodes} episodes)");
                    Console.WriteLine($"  Show ID: {shows[0]?.Id}");
                    Console.WriteLine($"  URN: {shows[0]?.Urn}");
                }
                else
                {
                    Console.WriteLine("✗ Failed: No shows returned");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 2: Get videos for a show
            Console.WriteLine("[Test 2] Fetch Videos for a Show");
            Console.WriteLine("--------------------------------");
            try
            {
                var shows = await apiClient.GetAllShowsAsync("srf", cancellationToken);
                if (shows != null && shows.Any())
                {
                    // Find a show with episodes
                    var showWithEpisodes = shows.FirstOrDefault(s => s.NumberOfEpisodes > 0);
                    if (showWithEpisodes != null && showWithEpisodes.Id != null)
                    {
                        Console.WriteLine($"Testing with show: {showWithEpisodes.Title}");

                        var videos = await apiClient.GetVideosForShowAsync("srf", showWithEpisodes.Id, cancellationToken);
                        if (videos != null && videos.Any())
                        {
                            Console.WriteLine($"✓ Successfully fetched {videos.Count} videos");
                            var firstVideo = videos[0];
                            Console.WriteLine($"  First video: {firstVideo?.Title}");
                            Console.WriteLine($"  URN: {firstVideo?.Urn}");
                            Console.WriteLine($"  Duration: {firstVideo?.Duration / 1000}s");
                            Console.WriteLine($"  Date: {firstVideo?.Date}");
                            Console.WriteLine($"  Playable abroad: {firstVideo?.PlayableAbroad}");
                        }
                        else
                        {
                            Console.WriteLine("✗ Failed: No videos returned");
                        }
                    }
                    else
                    {
                        Console.WriteLine("✗ Failed: No shows with episodes found");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 3: Get video stream URL using Integration Layer
            Console.WriteLine("[Test 3] Get Stream URL for Video");
            Console.WriteLine("---------------------------------");
            try
            {
                var shows = await apiClient.GetAllShowsAsync("srf", cancellationToken);
                if (shows != null && shows.Any())
                {
                    var showWithEpisodes = shows.FirstOrDefault(s => s.NumberOfEpisodes > 0);
                    if (showWithEpisodes != null && showWithEpisodes.Id != null)
                    {
                        var videos = await apiClient.GetVideosForShowAsync("srf", showWithEpisodes.Id, cancellationToken);
                        if (videos != null && videos.Any())
                        {
                            var video = videos[0];
                            if (video.Urn != null)
                            {
                                Console.WriteLine($"Fetching stream for: {video.Title}");

                                // Use Integration Layer 2.0 to get stream URL
                                var mediaComposition = await apiClient.GetMediaCompositionByUrnAsync(video.Urn, cancellationToken);
                                if (mediaComposition?.ChapterList != null && mediaComposition.ChapterList.Any())
                                {
                                    var chapter = mediaComposition.ChapterList[0];
                                    if (chapter.ResourceList != null && chapter.ResourceList.Any())
                                    {
                                        var hlsResource = chapter.ResourceList.FirstOrDefault(r =>
                                            r.Protocol == "HLS" && r.IsPlayable);

                                        if (hlsResource != null)
                                        {
                                            Console.WriteLine($"✓ Stream URL found:");
                                            Console.WriteLine($"  URL: {hlsResource.Url?.Substring(0, Math.Min(80, hlsResource.Url?.Length ?? 0))}...");
                                            Console.WriteLine($"  Quality: {hlsResource.Quality}");
                                            Console.WriteLine($"  Protocol: {hlsResource.Protocol}");
                                        }
                                        else
                                        {
                                            Console.WriteLine("✗ No HLS stream without DRM found");
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("✗ No resources found");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("✗ Failed to fetch media composition");
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 4: Check multiple shows
            Console.WriteLine("[Test 4] Check Multiple Shows");
            Console.WriteLine("----------------------------");
            try
            {
                var shows = await apiClient.GetAllShowsAsync("srf", cancellationToken);
                if (shows != null)
                {
                    var showsWithEpisodes = shows.Where(s => s.NumberOfEpisodes > 0).Take(10).ToList();
                    Console.WriteLine($"Checking {showsWithEpisodes.Count} shows with episodes...\n");

                    int successCount = 0;
                    foreach (var show in showsWithEpisodes)
                    {
                        if (show.Id != null)
                        {
                            var videos = await apiClient.GetVideosForShowAsync("srf", show.Id, cancellationToken);
                            if (videos != null && videos.Any())
                            {
                                Console.WriteLine($"✓ {show.Title}: {videos.Count} videos available");
                                successCount++;
                            }
                            else
                            {
                                Console.WriteLine($"✗ {show.Title}: No videos found");
                            }
                        }
                    }

                    Console.WriteLine();
                    Console.WriteLine($"Summary: {successCount}/{showsWithEpisodes.Count} shows successfully fetched videos");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 5: Test all business units
            Console.WriteLine("[Test 5] Test All Business Units");
            Console.WriteLine("--------------------------------");
            var businessUnits = new[] { "srf", "rts", "rsi", "rtr", "swi" };

            foreach (var bu in businessUnits)
            {
                try
                {
                    var shows = await apiClient.GetAllShowsAsync(bu, cancellationToken);
                    if (shows != null && shows.Any())
                    {
                        Console.WriteLine($"✓ {bu.ToUpper()}: {shows.Count} shows available");
                    }
                    else
                    {
                        Console.WriteLine($"✗ {bu.ToUpper()}: No shows found");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"✗ {bu.ToUpper()}: Error - {ex.Message}");
                }
            }
            Console.WriteLine();

            Console.WriteLine("=== Test Suite Complete ===");
        }
    }
}
