using MailKit;
using MailKit.Net.Imap;
using MailKit.Search;
using MailKit.Security;
using MimeKit;
using Services.ReActAgent;
using System.Collections.ObjectModel;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using ToolsServices;

namespace Services
{
    public static class EmailService
    {
        public enum eTypeSensibilite
        {
            Ton,
            Posture,
            Couleur,
            NiveauDetail
        }

        #region Variables privées
        
        private static readonly string NomFichierParamsMail = FichiersInternesService.ParamsMail;// "paramsMail.txt";
        private static readonly string NomFichierMails = FichiersInternesService.ListeMails;// "listeMails.json";
        private static ObservableCollection<EmailMessage>? Emails;
        private static ReActAgent.ReActAgent _ReActAgent = new();
        #endregion

        #region Méthodes publiques
        public static List<string> LoadSensibilites(eTypeSensibilite eSensibilite)
        {
            LoggerService.LogInfo($"EmailService.LoadSensibilites : {eSensibilite}");
            var nomFile = "";
            var contenu = "";
            switch(eSensibilite)
            {
                case eTypeSensibilite.Ton:
                    nomFile = FichiersInternesService.EmailsSensibiliteTon;
                    contenu = "Formel;Professionnel neutre;Chaleureux / convivial;Urgent / alerte;Didactique / explicatif;Persuasif / engageant";
                    break;
                case eTypeSensibilite.Posture:
                    nomFile = FichiersInternesService.EmailsSensibilitePosture;
                    contenu = "D’égal à égal;Hiérarchique (vers le haut ou vers le bas);De cadrage (donner des instructions, poser un cadre);De demandeur;De médiateur / facilitateur;D’alerte / vigilance;De soutien / collaboratif";
                    break;
                case eTypeSensibilite.Couleur:
                    nomFile = FichiersInternesService.EmailsSensibiliteCouleur;
                    contenu = "Politesse (sobre → très formelle);Enthousiasme (positif, motivant);Gravité (sérieux, solennel);Humour (léger, complice);Sarcasme (ironique, risqué)";
                    break;
                case eTypeSensibilite.NiveauDetail:
                    nomFile = FichiersInternesService.EmailsSensibiliteNiveauDetail;
                    contenu = "Simple et conçis;simple, objectif clair;structuré et nuancé;précision lexicale et stylistique;stratégie relationnelle autour du mail";
                    break;
            }
            var lst = new List<string>();
            if (File.Exists(nomFile))
            {
                string[] lignes = File.ReadAllLines(nomFile);
                foreach (string line in lignes)
                {
                    lst.Add(line);
                }
            }
            else
            {
                lst = new(contenu.Split(";").Select(x => x.Trim()).Where(x => !string.IsNullOrEmpty(x)));
                SaveSensibilite(eSensibilite, lst);
            }
            return lst.OrderBy(x=>x).ToList();
        }

        public static bool SaveSensibilite(eTypeSensibilite eSensibilite, List<string> lst, string newSensibilite="")
        {
            LoggerService.LogInfo($"EmailService.SaveSensibilite : {eSensibilite}");
            try
            {
                var nomFile = "";

                switch (eSensibilite)
                {
                    case eTypeSensibilite.Ton:
                        nomFile = FichiersInternesService.EmailsSensibiliteTon;
                        break;
                    case eTypeSensibilite.Posture:
                        nomFile = FichiersInternesService.EmailsSensibilitePosture;
                        break;
                    case eTypeSensibilite.Couleur:
                        nomFile = FichiersInternesService.EmailsSensibiliteCouleur;
                        break;
                    case eTypeSensibilite.NiveauDetail:
                        nomFile = FichiersInternesService.EmailsSensibiliteNiveauDetail;
                        break;
                }
                StringBuilder sb = new();
                foreach (var s in lst)
                {
                    if(s.Trim() != "")
                        sb.AppendLine(s.Trim());
                }
                if (newSensibilite != "")
                {
                    sb.AppendLine(newSensibilite.Trim());
                }
                
                var b = TxtService.CreateTextFile(nomFile, sb.ToString());
                if(!b)
                {
                    LoggerService.LogError($"EmailService.SaveSensibilite : Erreur lors de la sauvegarde du fichier {nomFile}");
                    return false;
                }

                return true;
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"EmailService.SaveSensibilite : {ex.Message}");
                return false;
            }
        }
        
        public async static Task<CompteMailUser?> LoadParametresAsync()
        {
            var p = LoadParametres();
            await Task.Delay(1);
            return p;
        }

        public static CompteMailUser? LoadParametres()
        {
            LoggerService.LogInfo("EmailService.LoadParametres");

            CompteMailUser SelectedItem = new();

            try
            {
                if (File.Exists(NomFichierParamsMail))
                {
                    SelectedItem.IsOk = true;

                    string[] lignes = File.ReadAllLines(NomFichierParamsMail);

                    if (lignes.Length > 0)
                        SelectedItem.ServeurImap = DecryptData(lignes[0]);

                    if (lignes.Length > 1)
                        SelectedItem.ServeurImapPort = int.Parse(lignes[1]);

                    if (lignes.Length > 2)
                        SelectedItem.ServeurSmtp = DecryptData(lignes[2]);

                    if (lignes.Length > 3)
                        SelectedItem.ServeurSmtpPort = int.Parse(lignes[3]);

                    if (lignes.Length > 4)
                        SelectedItem.UserAdresse = DecryptData(lignes[4]);

                    if (lignes.Length > 5)
                        SelectedItem.UserMotPasse = DecryptData(lignes[5]);

                    if (lignes.Length > 6)
                        SelectedItem.UserNomPrenom = DecryptData(lignes[6]);

                    if (lignes.Length > 7)
                        SelectedItem.UserRole = DecryptData(lignes[7]);

                    if (lignes.Length > 8)
                        SelectedItem.UserEntreprise = DecryptData(lignes[8]);

                    if (lignes.Length > 9)
                    {
                        if(int.TryParse(lignes[9], out int delay))
                            SelectedItem.DelayRefresh = delay;
                    }

                    if (lignes.Length > 10)
                    {
                        if (int.TryParse(lignes[10], out int delaySentRefresh))
                            SelectedItem.DelaySentRefresh = delaySentRefresh;
                    }

                    if (lignes.Length > 11)
                    {
                        if (int.TryParse(lignes[11], out int delaySentRecup))
                            SelectedItem.DelaySentRecup = delaySentRecup;
                    }

                    if (lignes.Length > 12)
                    {
                        if (int.TryParse(lignes[12], out int overdueDaysSentRecup))
                            SelectedItem.OverdueDaysSent = overdueDaysSentRecup;
                    }
                }
                return SelectedItem;

            }
            catch
            {
                return null;
            }
        }

        public async static Task<bool> SaveParametresAsync(CompteMailUser selectedItem)
        {
            var b = SaveParametres(selectedItem);
            await Task.Delay(1);
            return b;
        }

        public static bool SaveParametres(CompteMailUser selectedItem)
        {
            LoggerService.LogInfo("EmailService.SaveParametres");

            try
            {
                StringBuilder sb = new();

                sb.AppendLine(EncryptData(selectedItem.ServeurImap));
                sb.AppendLine(selectedItem.ServeurImapPort.ToString());
                sb.AppendLine(EncryptData(selectedItem.ServeurSmtp));
                sb.AppendLine(selectedItem.ServeurSmtpPort.ToString());
                sb.AppendLine(EncryptData(selectedItem.UserAdresse));
                sb.AppendLine(EncryptData(selectedItem.UserMotPasse));

                sb.AppendLine(EncryptData(selectedItem.UserNomPrenom));
                sb.AppendLine(EncryptData(selectedItem.UserRole));
                sb.AppendLine(EncryptData(selectedItem.UserEntreprise));

                sb.AppendLine(selectedItem.DelayRefresh.ToString());

                sb.AppendLine(selectedItem.DelaySentRefresh.ToString());
                sb.AppendLine(selectedItem.DelaySentRecup.ToString());
                sb.AppendLine(selectedItem.OverdueDaysSent.ToString());

                File.WriteAllText(NomFichierParamsMail, sb.ToString());
                selectedItem.IsOk = true;
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static async Task<ObservableCollection<EmailMessage>?> LireEmailsAsync(ObservableCollection<EmailMessage>? emails)
        {
            LoggerService.LogInfo("EmailService.LireEmailsAsync");

            Emails = emails;
            CompteMailUser? CompteMail = LoadParametres();
            if (CompteMail == null)
            {
                return null;
            }
            return await LoadUnreadEmailsAsync(CompteMail.UserAdresse, CompteMail.UserMotPasse, CompteMail.ServeurImap, CompteMail.ServeurImapPort, CompteMail.UserAdresse);
        }

        public static async Task<bool> EnvoyerMailAsync(MailKit.UniqueId? id, string destinataire, string sujet, string messageTexte, bool isReponse, string messageOrigineid, string destinataireCc="")
        {
            LoggerService.LogInfo("EmailService.EnvoyerReponseAsync");

            try
            {
                CompteMailUser? CompteMail = LoadParametres();
                if (CompteMail == null)
                {
                    return false;
                }
                var message = new MimeMessage();
                message.From.Add(MailboxAddress.Parse(CompteMail.UserAdresse)); // expéditeur

                var dests = destinataire.Split(';');
                foreach (var dest in dests)
                {
                    message.To.Add(MailboxAddress.Parse(dest));
                }

                if (destinataireCc != "")
                {
                    var destsCc = destinataireCc.Split(';');
                    foreach (var dest in destsCc)
                    {
                        message.Cc.Add(MailboxAddress.Parse(dest));
                    }
                }

                message.Subject = (isReponse & !sujet.StartsWith("RE:", StringComparison.CurrentCultureIgnoreCase) ? "RE: " + sujet : sujet);
                if(isReponse)
                {
                    message.InReplyTo = messageOrigineid;
                }

                // Version texte brut (fallback)
                var plainText = new TextPart("plain")
                {
                    Text = messageTexte
                };

                // Version HTML avec police Calibri et taille 12pt
                // on remplace les sauts de ligne par des paragraphes <p>
                var htmlParagraphs = string.Join("",
                            messageTexte
                                .Split('\n')
                                .Where(line => !string.IsNullOrWhiteSpace(line))
                                .Select(line => $"<p>{System.Net.WebUtility.HtmlEncode(line)}</p>")
                        );
                /*
                string signatureHtml = @"
                    <hr>
                        <table style=""width: 250px;"">
                          <tbody>
                            <tr>
                              <td style=""width: 96px; text-align: center;border-right-style: solid;border-right-width: 0px;padding-right: 20px;"">
                                <img src=""data:image/png;base64, "" alt=""All In IT"" style=""width: 96px; height: 80px;"">
                              </td>
                                <td style=""font-size: 14px; line-height: 1.3;padding-left: 15px;border-left-style: solid;border-left-width: 2px;font-family: Helvetica, sans-serif;white-space: nowrap;"">
                                <h1 style=""margin: 0; font-size: 16px;"">Guillaume TOPENOT</h1>
                                <p style=""margin: 0;color: #666;"">Manager</p>
                                <p style=""margin: 0;""><a href=""""></a></p>
                              </td>
                            </tr>
                          </tbody>
                        </table>";
                */
                string signatureHtml = "";
                var htmlText = new TextPart("html")
                {
                    Text = $"<html><body style='font-family: Calibri, sans-serif; font-size: 12pt;'>{htmlParagraphs+signatureHtml}</body></html>"
                };

                // Regroupe les deux versions (plain + html)
                var alternative = new MultipartAlternative();
                alternative.Add(plainText);
                alternative.Add(htmlText);

                // Ajoute au message
                message.Body = alternative;

                // --- Envoi via SMTP ---
                using var smtp = new MailKit.Net.Smtp.SmtpClient();
                await smtp.ConnectAsync(CompteMail.ServeurSmtp, CompteMail.ServeurSmtpPort, SecureSocketOptions.StartTls);
                await smtp.AuthenticateAsync(CompteMail.UserAdresse, CompteMail.UserMotPasse);
                await smtp.SendAsync(message);
                await smtp.DisconnectAsync(true);

                if (id != null)
                {
                    var Id = (MailKit.UniqueId)id;
                    await MarquerMessageCommeLu(Id, CompteMail.UserAdresse, CompteMail.UserMotPasse, CompteMail.ServeurImap, CompteMail.ServeurImapPort);
                }

                // --- Sauvegarde dans "Sent" via IMAP ---
                using var imap = new MailKit.Net.Imap.ImapClient();
                await imap.ConnectAsync(CompteMail.ServeurImap, CompteMail.ServeurImapPort, SecureSocketOptions.SslOnConnect);
                await imap.AuthenticateAsync(CompteMail.UserAdresse, CompteMail.UserMotPasse);

                // Accès à la boîte aux lettres personnelle (root)
                var personal = imap.GetFolder(imap.PersonalNamespaces[0]);

                // Récupérer le dossier "Sent"
                var sentFolder = await personal.GetSubfolderAsync("Sent");

                // Si ça ne marche pas (par exemple dossier en français "Envoyés") :
                if (sentFolder == null || !sentFolder.Exists)
                {
                    var allFolders = await personal.GetSubfoldersAsync(false);
                    sentFolder = allFolders.FirstOrDefault(f => f.Name.Equals("Sent", StringComparison.OrdinalIgnoreCase)
                                                              || f.Name.Equals("Envoyés", StringComparison.OrdinalIgnoreCase));
                }

                // Si on a bien trouvé un dossier "Sent" ou équivalent
                if (sentFolder != null)
                {
                    await sentFolder.OpenAsync(FolderAccess.ReadWrite);
                    await sentFolder.AppendAsync(message, MessageFlags.Seen);
                }

                LoggerService.LogDebug("Réponse par mail envoyée.");
                return true;
            }
            catch (Exception ex)
            {
                LoggerService.LogError(ex.ToString());
                return false;
            }
        }

        public static async Task<bool> MaquerLu(MailKit.UniqueId? id)
        {
            LoggerService.LogInfo("EmailService.MaquerLu");

            CompteMailUser? CompteMail = LoadParametres();
            if (CompteMail == null)
            {
                return false;
            }
            var b = await MarquerMessageCommeLu(id, CompteMail.UserAdresse, CompteMail.UserMotPasse, CompteMail.ServeurImap, CompteMail.ServeurImapPort);
            return b;
        }

        public static async Task<bool> SauvegarderReponseEmails(EmailMessage item)
        {
            try
            {
                LoggerService.LogInfo("EmailService.SauvegarderReponseEmails");
                await Task.Delay(1);
                if (!File.Exists(NomFichierMails))
                    return false;

                using FileStream fs = File.OpenRead(NomFichierMails);
                var items = JsonSerializer.Deserialize<ObservableCollection<EmailMessage>>(fs);
                fs.Close();
                if (items == null)
                {
                    return false;
                }

                var mail = items.FirstOrDefault(m => m.UidString == item.UidString);
                if (mail != null)
                {
                    mail.Reponse = item.Reponse;
                    var options = new JsonSerializerOptions { WriteIndented = true };
                    File.WriteAllText(NomFichierMails, JsonSerializer.Serialize(items, options));
                }

                return true;
            }
            catch (Exception ex) 
            {
                LoggerService.LogError($"{ex.Message}");
                return false;
            }
        }

        public static void SauvegarderEmails(ObservableCollection<EmailMessage> ListeItems)
        {
            try
            {
                LoggerService.LogInfo("EmailService.SauvegarderEmailsAsync");

                if (ListeItems == null)
                    return;

                var options = new JsonSerializerOptions
                {
                    WriteIndented = true,
                    // Ignore les propriétés non sérialisables comme UniqueId si nécessaire
                    IgnoreReadOnlyProperties = false,
                    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
                };

                if (File.Exists(NomFichierMails))
                    File.Delete(NomFichierMails);
                using FileStream fs = File.Create(NomFichierMails);
                JsonSerializer.Serialize(fs, ListeItems, options);
            }
            catch (Exception ex) 
            {
                LoggerService.LogError(ex.Message);
            }
        }

        public static ObservableCollection<EmailMessage> ChargerEmailsDepuisJson()
        {
            LoggerService.LogInfo("EmailService.ChargerEmailsDepuisJsonAsync");

            if (!File.Exists(NomFichierMails)) 
                return new ObservableCollection<EmailMessage>();

            using FileStream fs = File.OpenRead(NomFichierMails);
            var items = JsonSerializer.Deserialize<ObservableCollection<EmailMessage>>(fs);

            if (items == null)
            {
                return new ObservableCollection<EmailMessage>();
            }
            return items;
        }

        public static async Task<string> SeekByKeyWord(string RechercheString)
        {
            LoggerService.LogInfo("EmailService.SeekByKeyWord");
            var adressEmail = LoadParametres()?.UserAdresse ?? "";
            return await RAGService.Search(Domain.Emails, RechercheString, adressEmail);
        }

        public static bool SaveParametresCheckEmail(int val1, int val2)
        {
            try
            {
                StringBuilder sb = new();
                sb.AppendLine(val1.ToString());
                sb.AppendLine(val2.ToString());

                File.WriteAllText(FichiersInternesService.ParamsLancerCheckMails, sb.ToString());
                return true;
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"EmailService.SaveParametresCheckEmail Erreur : {ex.Message}");
                return false;
            }
        }

        public static (int, int) LoadParametresCheckEmail()
        {
            try
            {
                int val1 = 0;
                int val2 = 0;
                if (File.Exists(FichiersInternesService.ParamsLancerCheckMails))
                {
                    string[] lignes = File.ReadAllLines(FichiersInternesService.ParamsLancerCheckMails);

                    if (lignes.Length > 0)
                        val1 = int.Parse(lignes[0]);

                    if (lignes.Length > 1)
                        val2 = int.Parse(lignes[1]);

                }
                return (val1,val2);
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"EmailService.SaveParametresCheckEmail Erreur : {ex.Message}");
                return (0,0);
            }
        }

        public static async Task<(bool, string)> GenererMailAsync(string context, string query)
        {
            LoggerService.LogInfo($"EmailService.GenererMailAsync");
            var paramUser = LoadParametres();
            var prompt = PromptService.GetPrompt(PromptService.ePrompt.EmailService_Generer_Mail, query, context, paramUser!.UserNomPrenom, paramUser!.UserRole, paramUser!.UserEntreprise);
            LoggerService.LogDebug($"Prompt : {prompt}");

            var (textMail, m) = await _ReActAgent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.GenerationMail, true, prompt, "Génération d'email");
            LoggerService.LogDebug($"EmailService.GenererMailAsync : Modele : '{m}'\nMail généré : {textMail}");
            var b = textMail.Contains("Error", StringComparison.OrdinalIgnoreCase) || textMail.Contains("Exception", StringComparison.OrdinalIgnoreCase);
            return (!b, textMail);
        }

        #endregion

        #region Méthodes privées

        private static string EncryptData(string clairString)
        {
            LoggerService.LogDebug("EmailService.EncryptData");
            return CryptageService.EncryptData(clairString);

        }

        private static string DecryptData(string encryptedString)
        {
            LoggerService.LogDebug("EmailService.DecryptData");
            return CryptageService.DecryptData(encryptedString);

        }

        private static async Task<ObservableCollection<EmailMessage>> LoadUnreadEmailsAsync(string email, string password, string imapServer, int port, string proprietaire)
        {
            LoggerService.LogInfo("EmailService.LoadUnreadEmailsAsync");

            var messages = new ObservableCollection<EmailMessage>();

            using var client = new ImapClient();
            await client.ConnectAsync(imapServer, port, SecureSocketOptions.SslOnConnect);
            await client.AuthenticateAsync(email, password);

            var inbox = client.Inbox;
            await inbox.OpenAsync(FolderAccess.ReadOnly);

            var uids = await inbox.SearchAsync(SearchQuery.NotSeen);
            if(Emails != null && Emails.Count > 0)
            {
                foreach (var mail in Emails)
                {
                    bool isAbsentDansInbox = false;
                    if (Emails != null)
                    {
                        isAbsentDansInbox = !uids.Any(e => e == mail.Uid);
                        if(isAbsentDansInbox)
                        {
                            // Si l'email n'est pas dans la liste des non lus, on le marque pour suppression
                            mail.ToRemove = true; ;
                        }
                    }
                }
            }


            foreach (var uid in uids)
            {
                bool isExistDansListe = false;
                if (Emails != null)
                {
                    isExistDansListe = Emails.Any(e => e.Uid == uid);
                }

                if (!isExistDansListe)
                {
                    var message = await inbox.GetMessageAsync(uid);

                    EmailMessage msg = (new EmailMessage
                    {
                        Uid = uid,
                        Id = message.MessageId,
                        To = string.Join(";", message.To.Mailboxes.Select(e => e.Address).ToList()),
                        Cc = string.Join(";", message.Cc.Mailboxes.Select(e => e.Address).ToList()),
                        FromName = message.From.Mailboxes.FirstOrDefault()?.Name ?? "",
                        From = message.From.Mailboxes.FirstOrDefault()?.Address ?? "",
                        Subject = message.Subject,
                        Date = message.Date.DateTime,
                        Preview = message.TextBody?.Substring(0, Math.Min(200, message.TextBody.Length)) ?? "",
                        TextBody = message.TextBody != null ? message.TextBody : "",
                        TextBodyHTML = message.HtmlBody != null ? message.HtmlBody : "",
                        InReplyTo = message.InReplyTo,
                        IsDestinatairePrincipal = string.Join(";", message.To.Mailboxes.Select(e => e.Address).ToList()).Contains(email, StringComparison.OrdinalIgnoreCase)

                    });

                    if(msg.TextBody == "" && message.HtmlBody != null)
                    {
                        msg.TextBody = HtmlToPlainText(message.HtmlBody);
                    }

                    // Ici, on vectorize et stocke le message
                    var identiteMessage = $"Du {msg.Date.ToString("dd/MM/yyyy hh:mm")} - De {msg.From} - Sujet : {msg.Subject}";
                    if (message.TextBody != null && message.TextBody != "")
                    {
                        await RAGService.IngestDocument(Domain.Emails,false, false, msg.TextBody, identiteMessage, msg.Subject,proprietaire);
                    }


                    if (message.Attachments != null && message.Attachments.Any())
                    {
                        msg.ContentPJ = new();
                        var listFullText = await ExtractAndSummarizeAttachments(message, identiteMessage);

                        if (listFullText != null && listFullText.Count > 0)
                        {
                            msg.ContentPJ = listFullText;
                        }
                    }


                    // Analyse du message par modele
                    msg = await AnalyserMail(msg);

                    messages.Add(msg);
                }
            }

            await client.DisconnectAsync(true);
            return messages;
        }

        private static async Task<string> TraitementPJ(string fullFilename,string filename, ReActAgent.ReActAgent reActRagAgent, string identiteMessage)
        {
            LoggerService.LogInfo("EmailService.TraitementPJ");

            string sReturn = "";

            string extractedText = FilesService.ExtractText(fullFilename);
            if (!string.IsNullOrWhiteSpace(extractedText))
            {
                //reActRagAgent.IngestDocument(extractedText, filename, identiteMessage);
                var chunks = Services.RAGService.ChunkText(extractedText);
                var (summary, model) = await reActRagAgent.SummarizeDocAsync("Résumé de PJ", chunks, false);

                sReturn = $"📎 {filename} :\n{summary}";
                LoggerService.LogDebug($"{model} \t {summary}");
            }
            else
            {
                sReturn = $"📎 {filename} :\n Fichier illisible... ";
            }

            return sReturn;
            
        }

        private static async Task<List<string>> ExtractAndSummarizeAttachments(MimeMessage message, string identiteMessage)
        {
            LoggerService.LogInfo("EmailService.ExtractAndSummarizeAttachments");

            var reActRagAgent = new Services.ReActAgent.ReActAgent();
            var summaries = new List<string>();

            foreach (var attachment in message.Attachments)
            {
                if (attachment is MimePart part)       
                {
                    var fileName = part.FileName ?? "piece_jointe.xxx";
                    var extension = Path.GetExtension(fileName).ToLowerInvariant();
                    var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + "_" + fileName);

                    LoggerService.LogInfo($"Traitement de la pièce jointe : {fileName}");
                    using (var stream = File.Create(tempPath))
                    await part.Content.DecodeToAsync(stream);
                    
                    if (FilesService.IsExtensionSupport(extension))
                    {
                        summaries.Add(await TraitementPJ(tempPath, fileName, reActRagAgent, identiteMessage));
                    }
                    else if (extension == ".zip")
                    {
                        var extractDir = Path.Combine(Path.GetTempPath(), "zip_" + Guid.NewGuid());
                        Directory.CreateDirectory(extractDir);

                        System.IO.Compression.ZipFile.ExtractToDirectory(tempPath, extractDir);
                        foreach (var innerFile in Directory.GetFiles(extractDir, "*.*", SearchOption.AllDirectories))
                        {
                            var filenameInZip = Path.GetFileName(innerFile);
                            LoggerService.LogInfo($"Traitement de la pièce jointe dans {fileName} : {filenameInZip}");

                            try
                            {
                                var ext = Path.GetExtension(innerFile).ToLowerInvariant();

                                if (FilesService.IsExtensionSupport(ext))
                                {
                                    summaries.Add(await TraitementPJ(innerFile, filenameInZip, reActRagAgent, identiteMessage));
                                }
                                else
                                {
                                    summaries.Add($"📎 {filenameInZip} :\n Format de fichier non pris en charge... ");
                                }
                            }
                            catch
                            {
                                summaries.Add($"📎 {filenameInZip} :\n Fichier illisible... ");
                            }
                        }

                        Directory.Delete(extractDir, true);
                    }
                    else
                    {
                        summaries.Add($"📎 {fileName} :\n Format de fichier non pris en charge... ");
                    }

                    File.Delete(tempPath);

                }

            }

            return summaries;
        }

        private static string HtmlToPlainText(string html)
        {
            LoggerService.LogInfo("EmailService.HtmlToPlainText");

            return System.Text.RegularExpressions.Regex.Replace(html, "<.*?>", string.Empty);
        }

        private static async Task<EmailMessage> AnalyserMail(EmailMessage email)
        {
            try
            {
                LoggerService.LogInfo($"EmailService.AnalyserMail : '{email.Subject}'");

                #region MAJ du modèle IA
                email.ModeleIA = ReActAgent.ReActAgent.GetModeleIA(ModelsUseCases.TypeUseCase.AnalyseMails);
                LoggerService.LogInfo($"Modèle utilisé : {email.ModeleIA}");
                #endregion

                #region Résumé
                bool isPromptInjection = false;
                string messagePromptInjection = "";
                var subject = _ReActAgent.CleanUserInput(email.Subject, out isPromptInjection);
                if (isPromptInjection)
                {
                    messagePromptInjection += "Le sujet de l'email contient des éléments suspects.\n";
                    email.PresenceSuspecte = true;
                }
                var textBody = _ReActAgent.CleanUserInput(email.TextBody, out isPromptInjection);
                if (isPromptInjection)
                {
                    messagePromptInjection = "Le corps de l'email contient des éléments suspects.\n";
                    email.PresenceSuspecte = true;
                }
                /*
                var promptResume = $@"
                    Tu es un assistant professionnel chargé d'analyser un e-mail.
                    Lis le contenu suivant et fais un résumé clair et concis.

                    Ensuite, indique explicitement :
                    - Une note d'importance entre 0 et 5 (5 étant la plus haute importance) avec justification si possible
                    - Une note d'urgence entre 0 et 5 (5 étant la plus haute importance) avec justification si possible

                    Format de réponse attendu :
                    Résumé : ...

                    Importance (0-5) : ...
                    Urgence (0-5) : ...

                    Objet : {subject}
                    Contenu : {textBody}";
                */
                var promptResume = PromptService.GetPrompt(PromptService.ePrompt.EmailService_AnalyserMail_Resume, subject, textBody);

                if (email.IsPJ)
                {
                    var contentPJ = _ReActAgent.CleanUserInput(email.ContentPJ_STR, out isPromptInjection); ;
                    //promptResume += $"\n\n Inclus dans le résumé l'analyse des pièces jointes dont voici le résumé : {contentPJ}";
                    promptResume += $"\n\n" + PromptService.GetPrompt(PromptService.ePrompt.EmailService_AnalyserMail_Resume_PJ, contentPJ);

                    if (isPromptInjection)
                    {
                        messagePromptInjection += "Le contenu des pièces jointes contient des éléments suspects.\n";
                        email.PresenceSuspecte = true;
                    }
                }

                LoggerService.LogDebug($"Génération Résumé de : '{email.Subject}'");
                var (resume, m1) = await _ReActAgent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.AnalyseMails, false, promptResume, "Résumé d'email");
                email.Resume = messagePromptInjection + resume;

                var (important, urgent, importanceScore, urgenceScore, analyse) = ExtrairePriorites(resume);
                email.IsImportant = important;
                email.IsUrgent = urgent;
                email.ImportanceScore = importanceScore;
                email.UrgenceScore = urgenceScore;
                email.Analyse = analyse;
                #endregion

                #region Catégorie
                /*
                var promptCategorie = $@"
                    Tu dois catégoriser un email en fonction de son contenu.
                    Voici le résumé de l'email :
                    {resume}

                    Catégorise ce message parmi les choix suivants :
                    - Demande d'information
                    - Réclamation
                    - Demande de devis
                    - Problème technique
                    - Autre
                    Réponds uniquement par une des catégories listées.";
                */
                var promptCategorie = PromptService.GetPrompt(PromptService.ePrompt.EmailService_AnalyserMail_Categorie, resume);
                LoggerService.LogInfo($"Génération Catégorie de : '{email.Subject}'");
                var (categorie,m2) = await _ReActAgent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.AnalyseMails, false, promptCategorie, "Catégorie d'email");
                email.Categorie = categorie;
                #endregion

                #region Stratégie
                /*
                var promptStrategie = $@"
                    Tu dois choisir une stratégie de réponse à un email.

                    Catégorie : {categorie}
                    Important : {(important ? "oui" : "non")}
                    Urgent : {(urgent ? "oui" : "non")}

                    Voici les options possibles :
                    - Répondre avec une explication simple
                    - Demander plus d'informations
                    - Présenter des excuses et proposer une solution
                    - Accuser réception et informer d'un délai

                    Choisis la stratégie la plus adaptée en tenant compte de la **catégorie**, de l'**importance** et de l'**urgence**.";
                */
                var promptStrategie = PromptService.GetPrompt(PromptService.ePrompt.EmailService_AnalyserMail_Strategie, categorie, (important ? "oui" : "non"), (urgent ? "oui" : "non"));
                LoggerService.LogInfo($"Génération Stratégie de : '{email.Subject}'");
                var (strategie, m3) = await _ReActAgent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.AnalyseMails, false, promptStrategie, "Stratégie d'email");
                email.Strategie = strategie;
                #endregion

                #region Réponse proposée
                var paramUser = LoadParametres();
                /*
                var promptReponse = $@"
                    Rédige une réponse professionnelle à cet email en suivant la stratégie définie.

                    Objet : {email.Subject}
                    Contenu : {email.TextBody}
                    Résumé : {resume}
                    Catégorie : {categorie}
                    Stratégie : {strategie}

                    La réponse doit être claire, polie, adaptée au contexte et suffisamment concise.
                    Voici la signature à insérer en fin de mail :
                    Cordialement,
                    {paramUser!.UserNomPrenom}
                    {paramUser!.UserRole}
                    {paramUser!.UserEntreprise}";
                */
                var promptReponse = PromptService.GetPrompt(PromptService.ePrompt.EmailService_AnalyserMail_Reponse, email.Subject, email.TextBody, resume, categorie, strategie, paramUser!.UserNomPrenom, paramUser!.UserRole, paramUser!.UserEntreprise);
                if (email.IsPJ)
                {
                    //promptReponse += $"\n\n Inclus dans la réponse proposée l'analyse des pièces jointes dont voici le résumé : {email.ContentPJ_STR}";
                    promptReponse += $"\n\n" + PromptService.GetPrompt(PromptService.ePrompt.EmailService_AnalyserMail_Reponse_PJ, email.ContentPJ_STR);

                }

                LoggerService.LogInfo($"Génération Réponse proposée de : '{email.Subject}'");
                var (reponse,m4) = await _ReActAgent.AppelerLLMAsync(ModelsUseCases.TypeUseCase.AnalyseMails, false, promptReponse, "Réponse proposée d'email");
                email.Reponse = reponse;
                #endregion

                LoggerService.LogInfo($"Analyse d'un mail terminée : '{email.Subject}'");
                return email;
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"Erreur lors de l'analyse du mail '{email.Subject}': {ex.Message}");
                email.Reponse = "Une erreur est survenue lors de l'analyse de cet email.";
                return email;

            }
        }

        private static (bool important, bool urgent, int importanceScore, int urgenceScore, string analyse) ExtrairePriorites(string resume)
        {
            LoggerService.LogInfo("EmailService.ExtrairePriorites");

            //var important = resume.Contains("Important : oui", StringComparison.OrdinalIgnoreCase);
            //var urgent = resume.Contains("Urgent : oui", StringComparison.OrdinalIgnoreCase);

            int importanceScore = ExtraireScore(resume, "Importance");
            int urgenceScore = ExtraireScore(resume, "Urgence");
            string analyse = ExtraireAnalyse(resume, "Analyse");

            var important = (importanceScore > 2);
            var urgent = (urgenceScore > 2);

            return (important, urgent, importanceScore, urgenceScore, analyse);
        }

        private static int ExtraireScore(string texte, string motCle)
        {
            LoggerService.LogInfo("EmailService.ExtraireScore");

            // Cette regex gère :
            // - "Importance (0-5) : 4"
            // - "Importance (0-5):4"
            // - "Importance (4/5) : ..."
            // - "Importance: 4/5"
            // - avec ou sans espaces

            var pattern = $@"{motCle}\s*(?:\(\s*0\s*[--–—]\s*5\s*\)\s*:?\s*(\d)|\(\s*(\d)\s*/\s*5\s*\)|:?\s*(\d)\s*/\s*5)";
            var match = System.Text.RegularExpressions.Regex.Match(texte, pattern, RegexOptions.IgnoreCase);

            if (match.Success)
            {
                // On prend le premier groupe non vide (selon le format rencontré)
                for (int i = 1; i < match.Groups.Count; i++)
                {
                    if (match.Groups[i].Success)
                        return int.Parse(match.Groups[i].Value);
                }
            }

            return 0;
        }

        private static string ExtraireAnalyse(string texte, string motCle)
        {
            if (string.IsNullOrWhiteSpace(texte) || string.IsNullOrWhiteSpace(motCle))
                return string.Empty;

            // Échappe le mot-clé pour éviter les problèmes si motCle contient des caractères regex spéciaux
            var escaped = Regex.Escape(motCle);

            // 1) Pattern principal : capture un mot (lettres Unicode, -, +) juste après "Analyse :"
            var pattern = $@"\b{escaped}\s*:\s*([\p{{L}}\-+]+)";
            var match = Regex.Match(texte, pattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

            if (match.Success)
                return match.Groups[1].Value; // "Neutre"

            // 2) Fallback : capture la portion jusqu'à la fin de la ligne ou jusqu'à une ponctuation,
            // puis on prend le premier token (au cas où il y aurait du texte additionnel sur la même ligne)
            pattern = $@"\b{escaped}\s*:\s*([^\r\n\.\,\;\:\!\?]+)";
            match = Regex.Match(texte, pattern, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

            if (match.Success)
            {
                var s = match.Groups[1].Value.Trim();
                var first = s.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                return first.Length > 0 ? first[0] : string.Empty;
            }

            return string.Empty;
        }

        private static async Task<bool> MarquerMessageCommeLu(MailKit.UniqueId? id, string email, string password, string imapServer, int port)
            {
                LoggerService.LogInfo("EmailService.MarquerMessageCommeLu");

                try
                {
                    using var client = new ImapClient();
                    await client.ConnectAsync(imapServer, port, SecureSocketOptions.SslOnConnect);
                    await client.AuthenticateAsync(email, password);

                    var inbox = client.Inbox;
                    await inbox.OpenAsync(FolderAccess.ReadWrite);

                    if(id.HasValue) // Marque comme lu
                        await inbox.AddFlagsAsync(id.Value, MessageFlags.Seen, true); // Marque comme lu

                    await client.DisconnectAsync(true);

                    await Task.Delay(1);
                    LoggerService.LogInfo("Mail marqué comme 'lu'");
                    return true;
                }
                catch (Exception ex)
                {
                    LoggerService.LogError(ex.ToString());
                    return false;
                }
            }

        #endregion

        #region Conservés pour la culture

        private static async Task<MimeMessage?> GetLastUnreadEmailAsync(string email, string password, string imapServer, int port = 993)
        {
            using var client = new ImapClient();
            await client.ConnectAsync(imapServer, port, SecureSocketOptions.SslOnConnect);
            await client.AuthenticateAsync(email, password);

            var inbox = client.Inbox;
            await inbox.OpenAsync(MailKit.FolderAccess.ReadOnly);

            // Récupère tous les messages non lus
            var uids = await inbox.SearchAsync(SearchQuery.NotSeen);
            if (!uids.Any()) return null;

            // On prend le dernier non lu
            var lastUnread = uids.Last();
            var message = await inbox.GetMessageAsync(lastUnread);

            await client.DisconnectAsync(true);
            return message;
        }

        private static async Task<MimeMessage> LireDernierEmailAsync(string email, string password, string imapServer, int port = 993)
        {
            using var client = new ImapClient();
            await client.ConnectAsync(imapServer, port, SecureSocketOptions.SslOnConnect);
            await client.AuthenticateAsync(email, password);

            var inbox = client.Inbox;
            await inbox.OpenAsync(MailKit.FolderAccess.ReadOnly);
            var message = await inbox.GetMessageAsync(inbox.Count - 1);
            await client.DisconnectAsync(true);
            return message;
        }


        #endregion
    }
}
