using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Reflection;
using System.Security.Cryptography;

namespace JellyfinRPC
{
    class JellyfinAPI
    {
        public static async Task<string> Jellyfin()
        {
            
            while (true)
            {
                try
                {
                    var playingInfo = await GetCurrentlyPlaying();
                    if (playingInfo != null)
                    {
                        JToken nowPlaying = playingInfo.NowPlayingItem;

                        string largeImageKey = playingInfo.IsMusic
                            ? GetAlbumCover(nowPlaying)
                            : await GetJellyfinLogo();
                        string largeImageText = playingInfo.IsMusic
                            ? nowPlaying["Album"]?.ToString() ?? "Unknown Album"
                            : "Jellyfin";

                        string details = playingInfo.IsMusic
                            ? $"{playingInfo.Title}"
                            : nowPlaying["SeriesName"] != null
                                ? $"Watching {nowPlaying["SeriesName"]} - {playingInfo.Title}"
                                : $"Watching {playingInfo.Title}";

                        string state = playingInfo.IsMusic
                            ? $"{playingInfo.Artist}"
                            : nowPlaying["SeriesName"] != null
                                ? $"Season {playingInfo.Season}, Episode {playingInfo.Episode}"
                                : "";
                        DateTime duration = playingInfo.Duration;

                        DateTime progress = playingInfo.Progress;
    
                        return $"{largeImageKey}|{largeImageText}|{details}|{state}|{duration}|{progress}";
                    }
                }
                catch (Exception ex)
                {
                    ConsoleManager.WriteToConsole($"Error fetching Jellyfin data: {ex.Message}");
                }
            }
        }


        public static string AssemblyVersion
        {
            get
            {
                return Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }
        }
        private static async Task<string> GetJellyfinLogo()
        {
            using var httpClient = new HttpClient();
            try
            {
                if (ConfigManager.GetEntry("JellyfinToken") == "")
                {


                    var response = await httpClient.GetAsync($"{ConfigManager.GetEntry("ServerURL")}/System/Info?api_key={ConfigManager.GetEntry("APIKey")}");
                    response.EnsureSuccessStatusCode();

                    var jsonResponse = await response.Content.ReadAsStringAsync();
                    var json = JArray.Parse(jsonResponse);

                    var logoUrl = json["LogoUrl"]?.ToString();

                    return logoUrl ?? "jellyfin_logo";
                }
                else
                {
                    return "jellyfin_logo";
                }
            }
            catch (Exception ex)
            {
                ConsoleManager.WriteToConsole($"Error fetching Jellyfin logo: {ex.Message}");
                return "jellyfin_logo";
            }

        }
        private static async Task<PlayingInfo?> GetCurrentlyPlaying()
        {
            using var httpClient = new HttpClient();
            try
            {
                if (ConfigManager.GetEntry("JellyfinToken") == "")
                {
                    var response = await httpClient.GetAsync($"{ConfigManager.GetEntry("ServerURL")}/Sessions?api_key={ConfigManager.GetEntry("APIKey")}");
                    response.EnsureSuccessStatusCode();

                    var jsonResponse = await response.Content.ReadAsStringAsync();
                    var sessions = JArray.Parse(jsonResponse);

                    foreach (var session in sessions)
                    {
                        if (session["UserId"]?.ToString() == ConfigManager.GetEntry("UserID") && session["NowPlayingItem"] != null)
                        {
                            var nowPlaying = session["NowPlayingItem"];
                            var mediaType = nowPlaying["Type"]?.ToString();
                            bool isMusic = mediaType?.ToLower() == "audio";

                            string albumCover = "";
                            string artist = "Unknown Artist";

                            if (isMusic)
                            {
                                albumCover = GetAlbumCover(nowPlaying);
                                var artists = nowPlaying["Artists"]?.ToObject<JArray>();
                                if (artists != null && artists.Count > 0)
                                {
                                    artist = artists[0].ToString();
                                }
                                else
                                {
                                    artist = "Unknown Artist";
                                }

                            }

                            return new PlayingInfo
                            {
                                Title = nowPlaying["Name"]?.ToString(),
                                Artist = artist,
                                AlbumCover = albumCover,
                                Season = nowPlaying["ParentIndexNumber"]?.ToString() ?? "N/A",
                                Episode = nowPlaying["IndexNumber"]?.ToString() ?? "N/A",
                                Progress = new DateTime((long)session["PlayState"]["PositionTicks"]),
                                //Progress = TimeSpan.FromTicks((long)session["PlayState"]["PositionTicks"]),
                                Duration = new DateTime((long)nowPlaying["RunTimeTicks"]),
                                //Duration = TimeSpan.FromTicks((long)nowPlaying["RunTimeTicks"]),
                                IsMusic = isMusic,
                                NowPlayingItem = nowPlaying
                            };
                        }

                    }
                }
               
            }
            catch (Exception ex)
            {
                ConsoleManager.WriteToConsole($"Error fetching Jellyfin data: {ex.Message}");
            }
            return null;
        }

        private static string GetAlbumCover(JToken nowPlaying)
        {
            var mediaStreams = nowPlaying["MediaStreams"]?.ToObject<JArray>();
            if (mediaStreams != null)
            {
                foreach (var stream in mediaStreams)
                {
                    var imageTag = stream["ImageTag"]?.ToString();
                    if (!string.IsNullOrEmpty(imageTag))
                    {
                        return imageTag;
                    }
                }
            }
            return "album_cover";
        }
        public static async Task<string> SendQuickConnectRequest()
        {
            using var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Add("Authorization", $"MediaBrowser Client=\"JellyfinRPC\", Device=\"Windows, Probably\", DeviceId=\"{ConfigManager.GetEntry("JellyfinDeviceID")}\", Version=\"{AssemblyVersion}\"");
            if (ConfigManager.GetEntry("ServerURL") != "")
            {
                var response = await httpClient.PostAsync($"{ConfigManager.GetEntry("ServerURL")}/QuickConnect/Initiate", null);
                if (response.StatusCode is (System.Net.HttpStatusCode)401)
                {
                    System.Windows.Forms.MessageBox.Show("This server does not have Quick Connect enabled.", "Quick Connect Unavailable.", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error, System.Windows.Forms.MessageBoxDefaultButton.Button1);
                    return "Error: Server does not have Quick Connect Enabled.";
                }
                else
                {
                    try
                    {
                        response.EnsureSuccessStatusCode();
                        var jsonResponse = await response.Content.ReadAsStringAsync();
                        var contents = JArray.Parse(jsonResponse);

                        if (!contents.Any())
                        {
                            return "Error: Server did not respond.";
                        }

                        foreach (var content in contents)
                        {
                            if (content["Code"]?.ToString() != "")
                            {
                                return content["Code"]?.ToString();

                            }
                            else
                            {
                                return "Error: Server did not return code.";
                            }
                        }
                        return "Error: All values returned are null.";
                    }
                    catch (Exception ex)
                    {
                        return $"{ex.Message.Trim()}";
                    }

                }
            }
            else
            {
                return "Error: No Server URL Set.";
            }
        }

        public static string DeviceID()
        {
            using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
            {
                byte[] randomNumber = new byte[4];
                rng.GetBytes(randomNumber);
                int value = BitConverter.ToInt32(randomNumber, 0);
                byte[] valueBytes = System.Text.Encoding.UTF8.GetBytes(value.ToString());
                return System.Convert.ToBase64String(valueBytes);
            }

        }
    }
}
