using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CarManagerV3.Manager
{
    internal class Updater
    {

        private static readonly string GitApiUrl = "https://git.jaro.digital/api/v1";
        private static readonly string GitRepoOwner = "frozd";
        private static readonly string GitRepoName = "carmanager-3";
        private static readonly string GitApiRepoUrl = $"{GitApiUrl}/repos/{GitRepoOwner}/{GitRepoName}";
        private static readonly string LatestReleaseEndpoint = $"{GitApiRepoUrl}/releases/latest";
        private static readonly string PreReleaseEndpoint = $"{GitApiRepoUrl}/releases?limit=1&pre-release=true";
        private static string latestVersionCache = null;
        private static DateTime lastChecked = DateTime.MinValue;
        private static readonly int CacheDurationMinutes = 60;
        private static bool cacheIncludesPrerelease = false;
        private static readonly string debugVersion = null;//"1.2.0";
        private static bool isLatestVersionPrerelease = false;

        public static string GetCurrentVersion(bool cutTrailingZeros = false)
        {
            //DEBUG::
            if (debugVersion != null)
            {
                return debugVersion;
            }

            var asm = Assembly.GetEntryAssembly()!;
            Version v = asm.GetName().Version ?? new Version(0, 0, 0, 0);
            string VersionString = v.ToString();
            if(cutTrailingZeros)
            {
                // Remove trailing .0 parts
                while (VersionString.EndsWith(".0"))
                {
                    VersionString = VersionString.Substring(0, VersionString.Length - 2);
                }
                return VersionString;
            }
            return VersionString;
        }

        private static bool IsCacheValid(bool includePreRelease = false)
        {
            return includePreRelease == cacheIncludesPrerelease && latestVersionCache != null && (DateTime.Now - lastChecked).TotalMinutes < CacheDurationMinutes;
        }

        private static void InvalidateCache()
        {
            latestVersionCache = null;
            lastChecked = DateTime.MinValue;
        }

        private static void SetCache(string version, bool includePreRelease = false)
        {
            latestVersionCache = version;
            cacheIncludesPrerelease = includePreRelease;
            lastChecked = DateTime.Now;
        }


        public static string GetLatestVersion(bool includePreRelease = false)
        {
            if (IsCacheValid(includePreRelease))
            {
                System.Diagnostics.Debug.WriteLine("Using cached latest version: " + latestVersionCache);
                return latestVersionCache;
            }
            string latestVersion = null;
            // Get the latest stable version first
            using (var client = new System.Net.Http.HttpClient())
            {
                var response = client.GetAsync(LatestReleaseEndpoint).Result;
                if (response.IsSuccessStatusCode)
                {
                    var content = response.Content.ReadAsStringAsync().Result;
                    dynamic release = Newtonsoft.Json.JsonConvert.DeserializeObject(content);
                    latestVersion = release.tag_name;
                    isLatestVersionPrerelease = false;
                }
            }
            // If pre-release is requested, check for the latest pre-release version
            if (includePreRelease)
            {
                using (var client = new System.Net.Http.HttpClient())
                {
                    UrlEncoder encoder = System.Text.Encodings.Web.UrlEncoder.Default;
                    var response = client.GetAsync(PreReleaseEndpoint).Result;
                    if (response.IsSuccessStatusCode)
                    {
                        
                        var content = response.Content.ReadAsStringAsync().Result;
                        dynamic releases = Newtonsoft.Json.JsonConvert.DeserializeObject(content);
                        //System.Diagnostics.Debug.WriteLine("Fetched pre-release versions, count: " + releases.Count);
                        if (releases.Count > 0)
                        {
                            var preReleaseVersion = releases[0].tag_name.ToString();
                            //System.Diagnostics.Debug.WriteLine("Latest unstable version: " + preReleaseVersion);
                            
                            // Compare versions and return the newer one
                            if (IsNewerVersion(preReleaseVersion, latestVersion))
                            {
                                latestVersion = preReleaseVersion;
                                isLatestVersionPrerelease = true;
                            }
                        }
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("Failed to fetch pre-release versions, status code: " + response.StatusCode + " at: " + PreReleaseEndpoint);
                    }
                }
            }
            SetCache(latestVersion, includePreRelease);
            return latestVersion;

        }

        public static bool IsNewerVersion(string versionA, string versionB)
        {
            if (versionA == null) return false;
            if (versionB == null) return true;
            Version vA = new Version(versionA.TrimStart('v'));
            Version vB = new Version(versionB.TrimStart('v'));
            return vA > vB;
        }


        public static void DownloadNewestInstaller(bool includePreRelease = false)
        {
            string latestVersion = GetLatestVersion(includePreRelease);
            if (latestVersion == null)
            {
                throw new Exception("Could not fetch latest version from Git API.");
            }

            string releaseUrl = $"{GitApiRepoUrl}/releases/tags/{latestVersion}";
            using (var client = new System.Net.Http.HttpClient())
            {
                var response = client.GetAsync(releaseUrl).Result;
                if (response.IsSuccessStatusCode)
                {
                    var content = response.Content.ReadAsStringAsync().Result;
                    dynamic release = Newtonsoft.Json.JsonConvert.DeserializeObject(content);
                    string downloadUrl = null;
                    foreach (var asset in release.assets)
                    {
                        // file that ends with .msi
                        if (asset.name.ToString().EndsWith(".msi"))
                        {
                            downloadUrl = asset.browser_download_url;
                            break;
                        }
                    }

                    if (downloadUrl != null)
                    {


                        // Download the installer to the users set Data dir, run it, and then exit the application.
                        string tempFilePath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"CarManagerInstaller_{latestVersion}.msi");
                        using (var downloadClient = new System.Net.WebClient())
                        {
                            downloadClient.DownloadFile(downloadUrl, tempFilePath);
                        }
                        // Use ProcessStartInfo with UseShellExecute to launch the MSI file
                        var processStartInfo = new System.Diagnostics.ProcessStartInfo
                        {
                            FileName = tempFilePath,
                            UseShellExecute = true
                        };
                        System.Diagnostics.Process.Start(processStartInfo);


                        Application.Exit();
                    }
                    else
                    {
                        throw new Exception("Could not find installer asset in the latest release.");
                    }
                }
                else
                {
                    throw new Exception("Could not fetch release information from Git API.");

                }

            }
        }

        public static bool IsUpdateAvailable(bool includePreRelease = false)
        {
            string currentVersion = GetCurrentVersion();
            string latestVersion = GetLatestVersion(includePreRelease);
            return IsNewerVersion(latestVersion, currentVersion);
        }

        public static void OpenReleasePage(string version = null)
        {
            if (version == null)
            {
                version = GetLatestVersion(true);
            }
            string releaseUrl = $"https://git.jaro.digital/{GitRepoOwner}/{GitRepoName}/releases/tag/{version}";
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
            {
                FileName = releaseUrl,
                UseShellExecute = true
            });
        }

        public static bool IsLatestVersionPrerelease()
        {
            // Ensure we have the latest version info in cache
            return isLatestVersionPrerelease;
        }
    }
}
