using System;
using System.Drawing;
using System.Net;
using System.Windows.Forms;
using CarManagerV3.Forms;

namespace CarManagerV3
{
    /// <summary>
    /// The <c>ImageManager</c> class is responsible for managing car images, including fetching and storing them locally.
    /// </summary>
    internal class ImageManager
    {

        private static string _imagePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\CarManagerV3\\images";
        private static NetworkCredential myNetCred = null;
        private static bool disableImageFetch = false;

        /// <summary>
        /// Initializes the image folder by creating it if it does not exist.
        /// </summary>
        public static void InitializeImageFolder()
        {
            string path = _imagePath;
            
            if (!System.IO.Directory.Exists(path))
            {
                System.IO.Directory.CreateDirectory(path);
            }

            // Do not catch here. If we cannot create our images folder, the program wont work.
            
        }

        /// <summary>
        /// Generates the image path for a given car based on its attributes.
        /// </summary>
        /// <param name="car">The car.</param>
        /// <returns>The image path for this Car.</returns>
        public static string GetImagePath(Car car)
        {
            string basePath = $"{_imagePath}/";
            string fileName = $"{car.Make}_{car.Model}_{car.Year}_{car.Color}.png";
            return basePath + fileName;
        }

        /// <summary>
        /// Gets the image for a given car, fetching it if necessary.
        /// </summary>
        /// <param name="car">The car.</param>
        /// <returns>The <see cref="Image"/> object for the car.</returns>
        public static Image GetImage(Car car)
        {
            InitializeImageFolder();
            FetchImage(car);
            string path = GetImagePath(car);
            // does image exist?
            try
            {
                if (System.IO.File.Exists(path))
                {
                    return Image.FromFile(path);
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Error loading image: {ex.Message}");
            }
            try
            {
                return Image.FromFile($"{_imagePath}/no_image_available.png");
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Error loading fallback image: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// Fetches an image for a Car from https://cdn.imagin.studio/getimage if it does not already exist locally and saves it to images/<c>Make_Model_Year_Color.webp</>.
        /// If the image cannot be fetched, a placeholder image is used instead.
        /// Uses example customer id "hrjavascript-mastery", because they wouldn't give me one. Stole this from a tutorial page. :)
        /// </summary>
        /// <param name="car">The car.</param>
        public static void FetchImage(Car car)
        {
            // Fetch the image from https://cdn.imagin.studio/getimage and save it to images/Make_Model_Year.webp
            // use params like this: ?customer=hrjavascript-mastery&zoomType=fullscreen&make={make}&modelFamily={model}&modelYear={year}&angle=front&paintDescription={color}&fileType=png
            // check if the image already exists
            string path = GetImagePath(car);
            if (System.IO.File.Exists(path))
            {
                return;
            }
            if (disableImageFetch) return;
            string url = $"https://cdn.imagin.studio/getimage?customer=hrjavascript-mastery&zoomType=fullscreen&make={car.Make}&modelFamily={car.Model}&modelYear={car.Year}&angle=front&paintDescription={car.Color}&fileType=png";
            //add Referer header to avoid 403 error
            using (var client = new System.Net.WebClient())
            {
                client.Headers.Add("Referer", "http://localhost");
                if (myNetCred != null)
                {
                    client.Proxy.Credentials = myNetCred;
                }
                try
                {
                    if (myNetCred == null) throw new WebException();
                    client.DownloadFile(url, path);
                }
                catch (WebException ex)
                {
                    // is status code 407?
                    //if (ex.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired)
                    //{
                    //    Console.Error.WriteLine("Proxy authentication required. Prompting for credentials.");
                    //}

                    if (myNetCred != null)
                    {
                        DialogResult disableImgDialogRetry = MessageBox.Show("Something went wrong when fetching images. Are you credentials correct? Do you want to disable Image fetching for this session or rety with different credentials?", "Invalid Credentials", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if(disableImgDialogRetry == DialogResult.Cancel)
                        {
                            disableImageFetch = true;
                            return;
                        }
                    }
                    NetCredentials netCredForm = new NetCredentials();
                    DialogResult dialogRes = netCredForm.ShowDialog();
                    if (dialogRes == DialogResult.OK)
                    {
                        NetworkCredential netcred = netCredForm.GetCredentails();
                        myNetCred = netcred;
                        System.Diagnostics.Debug.WriteLine($"Got credentials: {netcred.UserName}, {netcred.Password}");
                        FetchImage(car);
                        return;
                    } else
                    {
                        DialogResult disableImgDialog = MessageBox.Show("Do you want to disable image fetching for this session?", "Disable Image fetching?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        if(disableImgDialog == DialogResult.Yes)
                        {
                            disableImageFetch = true;
                        } else
                        {
                            FetchImage(car);
                            return;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                    // if error, use fallback image no_image_available.png
                    //System.IO.File.Copy($"{_imagePath}/no_image_available.png", path);
                }
            }

        }
    }
}
