using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.SRFPlay.Api;
using Jellyfin.Plugin.SRFPlay.Api.Models;
using Jellyfin.Plugin.SRFPlay.Configuration;
using Jellyfin.Plugin.SRFPlay.Services;
using Microsoft.Extensions.Logging;

namespace Jellyfin.Plugin.SRFPlay.Tests
{
    /// <summary>
    /// Simple IHttpClientFactory implementation for tests.
    /// </summary>
    internal sealed class TestHttpClientFactory : IHttpClientFactory
    {
        public HttpClient CreateClient(string name) => new HttpClient();
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            // Run the new Play v3 API tests
            await TestPlayV3Api.RunTests();

            Console.WriteLine("\n\n");
            Console.WriteLine("=================================================================");
            Console.WriteLine("OLD API TESTS (DEPRECATED - Expected to fail)");
            Console.WriteLine("=================================================================\n");

            Console.WriteLine("=== SRFPlay Plugin Test Suite (Old API) ===\n");

            // Setup logging
            using var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder.AddConsole();
                builder.SetMinimumLevel(LogLevel.Warning); // Only show warnings and errors
            });

            var httpClientFactory = new TestHttpClientFactory();
            var apiClient = new SRFApiClient(loggerFactory);
            var streamResolver = new StreamUrlResolver(loggerFactory.CreateLogger<StreamUrlResolver>(), httpClientFactory);

            var cancellationToken = CancellationToken.None;

            // Test 1: Check API connectivity
            Console.WriteLine("[Test 1] API Connectivity Test");
            Console.WriteLine("-------------------------------");
            try
            {
                var latestVideos = await apiClient.GetLatestVideosAsync("srf", cancellationToken);
                if (latestVideos?.ChapterList != null && latestVideos.ChapterList.Any())
                {
                    Console.WriteLine($"✓ Successfully fetched latest videos: {latestVideos.ChapterList.Count} items");
                    Console.WriteLine($"  First video: {latestVideos.ChapterList[0]?.Title}");
                }
                else
                {
                    Console.WriteLine("✗ Failed: No videos returned");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 2: Check trending videos
            Console.WriteLine("[Test 2] Trending Videos Test");
            Console.WriteLine("-----------------------------");
            try
            {
                var trendingVideos = await apiClient.GetTrendingVideosAsync("srf", cancellationToken);
                if (trendingVideos?.ChapterList != null && trendingVideos.ChapterList.Any())
                {
                    Console.WriteLine($"✓ Successfully fetched trending videos: {trendingVideos.ChapterList.Count} items");
                    Console.WriteLine($"  First video: {trendingVideos.ChapterList[0]?.Title}");
                }
                else
                {
                    Console.WriteLine("✗ Failed: No videos returned");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 3: Get specific video and check stream URL
            Console.WriteLine("[Test 3] Stream URL Resolution Test");
            Console.WriteLine("-----------------------------------");
            try
            {
                var latestVideos = await apiClient.GetLatestVideosAsync("srf", cancellationToken);
                if (latestVideos?.ChapterList != null && latestVideos.ChapterList.Any())
                {
                    var firstChapter = latestVideos.ChapterList[0];
                    Console.WriteLine($"Testing with: {firstChapter.Title}");
                    Console.WriteLine($"URN: {firstChapter.Urn}");

                    // Fetch full media composition for this URN
                    var mediaComposition = await apiClient.GetMediaCompositionByUrnAsync(firstChapter.Urn, cancellationToken);

                    if (mediaComposition?.ChapterList != null && mediaComposition.ChapterList.Any())
                    {
                        var chapter = mediaComposition.ChapterList[0];

                        // Check if content is playable
                        bool hasPlayableContent = streamResolver.HasPlayableContent(chapter);
                        Console.WriteLine($"Has playable content: {hasPlayableContent}");

                        // Check if content is expired
                        bool isExpired = streamResolver.IsContentExpired(chapter);
                        Console.WriteLine($"Is expired: {isExpired}");

                        // Try to get stream URL
                        if (hasPlayableContent && !isExpired)
                        {
                            var streamUrl = streamResolver.GetStreamUrl(chapter, Jellyfin.Plugin.SRFPlay.Configuration.QualityPreference.Auto);
                            if (!string.IsNullOrEmpty(streamUrl))
                            {
                                Console.WriteLine($"✓ Stream URL resolved: {streamUrl.Substring(0, Math.Min(80, streamUrl.Length))}...");

                                // Show available resources
                                if (chapter.ResourceList != null)
                                {
                                    Console.WriteLine($"  Available resources: {chapter.ResourceList.Count}");
                                    foreach (var resource in chapter.ResourceList.Take(5))
                                    {
                                        var hasDrm = resource.DrmList != null && resource.DrmList.ToString() != "[]";
                                        Console.WriteLine($"    - {resource.Quality} ({resource.Protocol}) {(hasDrm ? "[DRM]" : "[No DRM]")}");
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("✗ Failed to resolve stream URL");
                            }
                        }
                        else
                        {
                            if (!hasPlayableContent)
                                Console.WriteLine("✗ Content is not playable (likely DRM protected)");
                            if (isExpired)
                                Console.WriteLine($"✗ Content is expired (ValidTo: {chapter.ValidTo})");
                        }
                    }
                    else
                    {
                        Console.WriteLine("✗ Failed to fetch media composition");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
                Console.WriteLine($"Stack trace: {ex.StackTrace}");
            }
            Console.WriteLine();

            // Test 4: Check multiple videos for playability
            Console.WriteLine("[Test 4] Multiple Videos Playability Check");
            Console.WriteLine("------------------------------------------");
            try
            {
                var latestVideos = await apiClient.GetLatestVideosAsync("srf", cancellationToken);
                if (latestVideos?.ChapterList != null)
                {
                    int totalVideos = Math.Min(10, latestVideos.ChapterList.Count);
                    int playableCount = 0;
                    int expiredCount = 0;
                    int drmCount = 0;

                    Console.WriteLine($"Checking {totalVideos} videos...\n");

                    for (int i = 0; i < totalVideos; i++)
                    {
                        var chapter = latestVideos.ChapterList[i];
                        var mediaComp = await apiClient.GetMediaCompositionByUrnAsync(chapter.Urn, cancellationToken);

                        if (mediaComp?.ChapterList != null && mediaComp.ChapterList.Any())
                        {
                            var fullChapter = mediaComp.ChapterList[0];
                            bool hasPlayable = streamResolver.HasPlayableContent(fullChapter);
                            bool isExpired = streamResolver.IsContentExpired(fullChapter);

                            string status;
                            if (isExpired)
                            {
                                status = "EXPIRED";
                                expiredCount++;
                            }
                            else if (!hasPlayable)
                            {
                                status = "DRM";
                                drmCount++;
                            }
                            else
                            {
                                status = "PLAYABLE";
                                playableCount++;
                            }

                            Console.WriteLine($"{i + 1}. [{status}] {fullChapter.Title}");
                        }
                    }

                    Console.WriteLine();
                    Console.WriteLine($"Summary:");
                    Console.WriteLine($"  Playable: {playableCount}/{totalVideos} ({(playableCount * 100.0 / totalVideos):F1}%)");
                    Console.WriteLine($"  DRM Protected: {drmCount}/{totalVideos} ({(drmCount * 100.0 / totalVideos):F1}%)");
                    Console.WriteLine($"  Expired: {expiredCount}/{totalVideos} ({(expiredCount * 100.0 / totalVideos):F1}%)");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

            // Test 5: Test library content discovery (simulates what would be in the library)
            Console.WriteLine("[Test 5] Library Content Discovery Simulation");
            Console.WriteLine("----------------------------------------------");
            try
            {
                var latestVideos = await apiClient.GetLatestVideosAsync("srf", cancellationToken);
                var trendingVideos = await apiClient.GetTrendingVideosAsync("srf", cancellationToken);

                var allUrns = new HashSet<string>();

                if (latestVideos?.ChapterList != null)
                {
                    foreach (var chapter in latestVideos.ChapterList)
                    {
                        if (!string.IsNullOrEmpty(chapter.Urn))
                            allUrns.Add(chapter.Urn);
                    }
                }

                if (trendingVideos?.ChapterList != null)
                {
                    foreach (var chapter in trendingVideos.ChapterList)
                    {
                        if (!string.IsNullOrEmpty(chapter.Urn))
                            allUrns.Add(chapter.Urn);
                    }
                }

                Console.WriteLine($"✓ Latest videos available: {latestVideos?.ChapterList?.Count ?? 0}");
                Console.WriteLine($"✓ Trending videos available: {trendingVideos?.ChapterList?.Count ?? 0}");
                Console.WriteLine($"✓ Total unique items for library (deduplicated): {allUrns.Count}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Error: {ex.Message}");
            }
            Console.WriteLine();

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

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

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