using System.Text;
using System.Text.Json;
using ToolsServices;

namespace Services.Fooocus
{
    public static class FooocusService
    {
        #region Méthodes publiques

        #region Gestion des paramètres

        public static (string, string, string) LoadParametresGenerateImg()
        {
            LoggerService.LogInfo("FooocusService.LoadParametresGenerateImg");

            string url = "";
            string endpointv1 = "";
            string endpointv2 = "";

            try
            {
                if (File.Exists(FichiersInternesService.ParamsGenerateImg))
                {

                    string[] lignes = File.ReadAllLines(FichiersInternesService.ParamsGenerateImg);

                    if (lignes.Length > 0)
                        url = lignes[0];

                    if (lignes.Length > 1)
                        endpointv1 = lignes[1];

                    if (lignes.Length > 2)
                        endpointv2 = lignes[2];

                }
                return (url, endpointv1, endpointv2);

            }
            catch
            {
                return ("", "", "");
            }
        }

        public static bool SaveParametresGenerateImg(string url, string endpointv1, string endpointv2)
        {
            LoggerService.LogInfo("FooocusService.SaveParametresGenerateImg");

            try
            {
                StringBuilder sb = new();
                sb.AppendLine(url);
                sb.AppendLine(endpointv1);
                sb.AppendLine(endpointv2);

                File.WriteAllText(FichiersInternesService.ParamsGenerateImg, sb.ToString());

                return true;
            }
            catch
            {
                return false;
            }

        }

        public static FooocusRequest_Text_to_Image LoadParametresFooocus()
        {
            LoggerService.LogInfo("FooocusService.LoadParametresFooocus");

            FooocusRequest_Text_to_Image param = new();

            try
            {
                if (File.Exists(FichiersInternesService.ParamsFooocus))
                {

                    string[] lignes = File.ReadAllLines(FichiersInternesService.ParamsFooocus);

                    if (lignes.Length > 0)
                        param.negative_prompt = lignes[0];

                    if (lignes.Length > 1)
                        param.guidance_scale = double.Parse(lignes[1]);

                    if (lignes.Length > 2)
                        param.performance_selection = lignes[2];

                    if (lignes.Length > 3)
                        param.sharpness = double.Parse(lignes[3]);

                    if (lignes.Length > 4)
                        param.style_selections = lignes[4].Split(',', StringSplitOptions.RemoveEmptyEntries) // coupe sur les virgules
                                                    .Select(s => s.Trim()) // enlève les espaces inutiles
                                                    .ToArray();
                }
                return param;

            }
            catch
            {
                return param;
            }
        }

        public static bool SaveParametresFooocus(FooocusRequest_Text_to_Image param, List<string> ListeSelectedsStylesFooocus)
        {
            LoggerService.LogInfo("FooocusService.SaveParametresFooocus");

            try
            {
                StringBuilder sb = new();
                sb.AppendLine(param.negative_prompt);
                sb.AppendLine(param.guidance_scale.ToString());
                sb.AppendLine(param.performance_selection);
                sb.AppendLine(param.sharpness.ToString());
                sb.AppendLine(string.Join(", ", ListeSelectedsStylesFooocus));

                File.WriteAllText(FichiersInternesService.ParamsFooocus, sb.ToString());

                return true;
            }
            catch
            {
                return false;
            }

        }
        #endregion

        #region Interactions
        public static async Task<bool> IsFooocusActif()
        {
            LoggerService.LogInfo($"FooocusService.IsFooocusActif");
            try
            {
                (string baseUrl, _, _) = LoadParametresGenerateImg();
                if (baseUrl == "")
                {
                    var msg = "Erreur de chargement des paramètres Fooocus.";
                    LoggerService.LogWarning(msg);
                    return false;
                }
                var url = $"{baseUrl}";
                using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(360) };

                client.Timeout = TimeSpan.FromSeconds(30);
                var response = await client.GetAsync(url);
                LoggerService.LogDebug($"FooocusService.IsFooocusActif : {response.IsSuccessStatusCode}");
                return response.IsSuccessStatusCode;
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"FooocusService.IsFooocusActif : False --> {ex.Message}");
                return false;
            }
        }

        public static async Task<List<string>> GetFooocusStylesAsync()
        {
            LoggerService.LogInfo("FooocusService.GetFooocusStylesAsync");

            (string baseUrl, _, _) = LoadParametresGenerateImg();
            var url = $"{baseUrl}/v1/engines/styles";
            if (url == "")
            {
                LoggerService.LogWarning("FooocusService.GetFooocusStylesAsync : URL de l'API de génération d'image non configurée.");
                var lst = new List<string>();
                lst.Add("URL de l'API de génération d'image non configurée.");
                return lst;
            }

            using var client = new HttpClient();

            var response = await client.GetAsync(url);
            response.EnsureSuccessStatusCode();

            var json = await response.Content.ReadAsStringAsync();

            // Le JSON est du type ["Fooocus V2","Random Style",...]
            var styles = JsonSerializer.Deserialize<List<string>>(json);

            return styles ?? new List<string>();
        }

        public static async Task<string> GenerateTextToImageWithIP(string promptFinal, List<string> imagesFullFilename)
        {
            LoggerService.LogInfo("FooocusService.GenerateTextToImageWithIP");

            (string baseUrl, _, string endpoint) = LoadParametresGenerateImg();
            //endpoint = "/v2/generation/text-to-image-with-ip";

            var images = new List<object>();
            double poidsTotal = 1.9;
            foreach (var img in imagesFullFilename)
            {
                poidsTotal = poidsTotal - 0.1;
                if (poidsTotal < 0.2)
                    poidsTotal = 0.2;

                var uneImg = new
                {
                    cn_img = Convert.ToBase64String(File.ReadAllBytes(img)),
                    cn_stop = 0.5,
                    cn_weight = poidsTotal,
                    cn_type = "ImagePrompt"
                };

                images.Add(uneImg);
            }



            var requestBody = new
            {
                prompt = promptFinal,
                image_prompts = images.ToArray()
            };

            var url = $"{baseUrl}{endpoint}";

            using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(360) };

            var json = JsonSerializer.Serialize(requestBody);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            // Envoi de la requête POST
            var response = await client.PostAsync($"{url}", content);
            response.EnsureSuccessStatusCode();

            // Lecture de la réponse JSON
            var responseJson = await response.Content.ReadAsStringAsync();

            // Désérialisation
            using var doc = JsonDocument.Parse(responseJson);

            var imageUrl = doc.RootElement[0].GetProperty("url").GetString();
            if (imageUrl == null)
            {
                return "";
            }
            imageUrl = imageUrl.Replace("http://127.0.0.1:8888", baseUrl);

            return $"{imageUrl}";

        }

        public static async Task<string> GenerateImageWithFooocus(FooocusRequest_Text_to_Image requestBody)
        {
            LoggerService.LogInfo("FooocusService.GenerateImageWithFooocus(requestBody)");

            try
            {
                (string baseUrl, string endpoint, _) = LoadParametresGenerateImg();
                var url = $"{baseUrl}{endpoint}";
                if (url == "")
                {
                    LoggerService.LogWarning("FooocusService.GenerateImageWithFooocus : URL de l'API de génération d'image non configurée.");
                    return "URL de l'API de génération d'image non configurée.";
                }

                using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(360) };

                var json = JsonSerializer.Serialize(requestBody);
                var content = new StringContent(json, Encoding.UTF8, "application/json");

                // Envoi de la requête POST
                var response = await client.PostAsync($"{url}", content);
                response.EnsureSuccessStatusCode();

                // Lecture de la réponse JSON
                var responseJson = await response.Content.ReadAsStringAsync();

                // Désérialisation
                using var doc = JsonDocument.Parse(responseJson);

                var imageUrl = doc.RootElement[0].GetProperty("url").GetString();
                if (imageUrl == null)
                {
                    return "";
                }
                imageUrl = imageUrl.Replace("http://127.0.0.1:8888", baseUrl);
                return $"{imageUrl}";
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"Erreur lors de la génération de l'image : {ex.Message}");
                return $"Erreur lors de la génération de l'image : {ex.Message}";
            }
        }

        public static async Task<string> GenerateImageWithFooocus(string prompt)
        {
            LoggerService.LogInfo("FooocusService.GenerateImageWithFooocus(prompt)");

            try
            {
                // Création du JSON à envoyer
                var requestBody = new FooocusRequest_Text_to_Image();
                if (File.Exists(FichiersInternesService.ParamsFooocus))
                {
                    requestBody = LoadParametresFooocus();
                }
                requestBody.prompt = prompt;

                /*
                Lora lora1 = new Lora()
                {
                    enabled = true,
                    model_name = "sd_xl_offset_example-lora_1.0.safetensors",
                    weight = 0.5
                };
                requestBody.loras.Append(lora1);
                */

                /*
                var requestBody = new 
                {
                    prompt = prompt,//"un chat steampunk sur un toit",
                    negative_prompt = "blurry, low quality, distorted, watermark, text, extra limbs, cropped",
                    guidance_scale = 9.0,
                    StyleSelections = new string[0],   // vide => pas d’expansion Fooocus V2
                    performance_selection = "Quality",
                    sharpness = 2.0,
                    image_seed = -1,
                    image_number = 1
                };
                */


                return await GenerateImageWithFooocus(requestBody);

            }
            catch (Exception ex)
            {
                LoggerService.LogError($"Erreur lors de la génération de l'image : {ex.Message}");
                return $"Erreur lors de la génération de l'image : {ex.Message}";
            }
        }
        #endregion

        #endregion
    }
}
