using Org.BouncyCastle.Ocsp;
using ReAct_PME.Domain;
using Services;
using Services.Models;
using Services.ReActAgent;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ReAct_PME.Application
{
    public class ChatRoomService : IChatRoomService
    {
        public async Task<string> EnvoiRequete_LLM(List<string> requete, IDT_CONVERSATIONService dt_conversationService, IDT_CONVERSATION_LIGNEService dt_conversation_ligneService, IDT_WORK_FORCEService dt_work_forceService)
        {
            var lst = new List<ChatMessage>();
            var message = new ChatMessage();
            message.Role = "user";
            message.Content = requete[0];
            lst.Add(message);
            Guid idConversation = Guid.NewGuid();
            Guid IdWorkForce = Guid.Empty;
            bool isNewConversation = true;
            DT_WORK_FORCE_DTO? wf = new();

            if (requete.Count >= 1)
            {
                if (requete[1] != null && requete[1] != "" && requete[1] != Guid.Empty.ToString())
                {
                    idConversation = Guid.Parse(requete[1]);
                    isNewConversation = false;
                }
            }
            if (requete.Count >= 2)
            {
                if (requete[2] != null && requete[2] != "" && requete[2] != Guid.Empty.ToString())
                {
                    IdWorkForce = Guid.Parse(requete[2]);
                    wf = await dt_work_forceService!.GetById_Async(IdWorkForce!);
                }
            }

            var (b, s, m) = await Services.ChatService.SendMessageAsync(ModelsUseCases.TypeUseCase.LLM, lst, "", false);
            bool isCreatedSuccess = false;
            if (b)
            {
                // Créer une nouvelle conversation 
                if (isNewConversation)
                {
                    DT_CONVERSATION_DTO item = new();
                    item.ID_CONVERSATION = idConversation;
                    item.LIBELLE = requete[0].Length <= 50 ? requete[0] : requete[0].Substring(0, 47) + "...";
                    item.DATE_START = DateTime.Now;
                    item.SystemDateCreated = DateTime.Now;
                    item.SystemDateUpdated = DateTime.Now;
                    item.IsEnabled = true;
                    item.TypeConv = "LLM";
                    item.ID_WORK_FORCE = IdWorkForce;
                    item.DT_WORK_FORCE = wf;

                    isCreatedSuccess = await dt_conversationService.Create_Async(item);
                }
                // Créer une nouvelle conversation-ligne
                if (isCreatedSuccess)
                {
                    DT_CONVERSATION_LIGNE_DTO ligne = new();
                    ligne.ID_CONVERSATION_LIGNE = Guid.NewGuid();
                    ligne.ID_CONVERSATION = idConversation;
                    ligne.DATE = DateTime.Now;
                    ligne.QUESTION = requete[0];
                    ligne.REPONSE = s;
                    ligne.MODELE = m;
                    ligne.SystemDateCreated = DateTime.Now;
                    ligne.SystemDateUpdated = DateTime.Now;
                    ligne.IsEnabled = true;

                    await dt_conversation_ligneService.Create_Async(ligne);
                }


            }
            return s;// "Réponse du service ChatRoomService";
        }

        public async Task<string> EnvoiRequete_RAG(List<string> requete, IDT_CONVERSATIONService dt_conversationService, IDT_CONVERSATION_LIGNEService dt_conversation_ligneService, IDT_WORK_FORCEService dt_work_forceService)
        {

            //var lst = new List<ChatMessage>();
            //var message = new ChatMessage();
            Guid idConversation = Guid.NewGuid();
            Guid IdWorkForce = Guid.Empty;
            //message.Role = "user";
            //message.Content = requete[0];
            //lst.Add(message);
            bool isNewConversation = true;
            DT_WORK_FORCE_DTO? wf = new();

            if (requete.Count >= 2)
            {
                if (requete[2] != null && requete[2] != "" && requete[2] != Guid.Empty.ToString())
                {
                    idConversation = Guid.Parse(requete[2]);
                    isNewConversation = false;
                }
            }
            if (requete.Count >= 3)
            {
                if (requete[3] != null && requete[3] != "" && requete[3] != Guid.Empty.ToString())
                {
                    IdWorkForce = Guid.Parse(requete[3]);
                    wf = await dt_work_forceService!.GetById_Async(IdWorkForce!);
                }
            }

            Services.Domain domain = DomainExtensions.GetDomainByCollectionName(requete[1]);
            var (b, s, m) = await RAGService.RechercheDansDocuments(domain, requete[0], "", false);

            bool isCreatedSuccess = false;
            if (b)
            {
                // Créer une nouvelle conversation 
                if (isNewConversation)
                {
                    DT_CONVERSATION_DTO item = new();
                    item.ID_CONVERSATION = idConversation;
                    item.LIBELLE = requete[0].Length <= 50 ? requete[0] : requete[0].Substring(0, 47) + "...";
                    item.DATE_START = DateTime.Now;
                    item.SystemDateCreated = DateTime.Now;
                    item.SystemDateUpdated = DateTime.Now;
                    item.IsEnabled = true;
                    item.TypeConv = "RAG";
                    item.ID_WORK_FORCE = IdWorkForce;
                    item.DT_WORK_FORCE = wf;

                    isCreatedSuccess = await dt_conversationService.Create_Async(item);
                }
                // Créer une nouvelle conversation-ligne
                if (isCreatedSuccess)
                {
                    DT_CONVERSATION_LIGNE_DTO ligne = new();
                    ligne.ID_CONVERSATION_LIGNE = Guid.NewGuid();
                    ligne.ID_CONVERSATION = idConversation;
                    ligne.DATE = DateTime.Now;
                    ligne.QUESTION = requete[0];
                    ligne.REPONSE = s;
                    ligne.MODELE = m;
                    ligne.SystemDateCreated = DateTime.Now;
                    ligne.SystemDateUpdated = DateTime.Now;
                    ligne.IsEnabled = true;
                    ligne.DomainRAG = requete[1];

                    await dt_conversation_ligneService.Create_Async(ligne);
                }


            }


            //var (b, s, m) = await Services.ChatService.SendMessageAsync(ModelsUseCases.TypeUseCase.RAG, lst, "", false);

            return s;// "Réponse du service RAGService";
        }

        public async Task<List<string>> ListeDomaines_RAG()
        {
            await Task.Delay(1);
            return Services.DomainExtensions.CollectionsNameRestricted;
        }

        public async Task<List<ConversationDto>?> GetConversations(Guid Id, IDT_CONVERSATIONService dt_conversationService)
        {
            var lstB = await dt_conversationService.GetAll_By_ID_WORK_FORCE_Async(Id);
            var lstConv = lstB.Where(c => c.IsEnabled == true).ToList();
            var result = new List<ConversationDto>();

            if (lstConv != null)
            {

                foreach (var oneConv in lstConv)
                {
                    ConversationDto conv = new();
                    conv.Id = oneConv.ID_CONVERSATION.ToString();
                    conv.IdWorkForce = oneConv.ID_WORK_FORCE.ToString();
                    conv.TypeConv = oneConv.TypeConv;
                    conv.Date = oneConv.DATE_START;
                    conv.Title = oneConv.LIBELLE;

                    if (oneConv.DT_CONVERSATION_LIGNEs != null && oneConv.DT_CONVERSATION_LIGNEs.Count > 0)
                    {
                        var lstMessageOrder = oneConv.DT_CONVERSATION_LIGNEs.Where(m => m.IsEnabled == true).OrderBy(c => c.DATE).ToList();
                        var lstMsg = new List<MessageDto>();

                        foreach (var oneMessage in lstMessageOrder!)
                        {
                            MessageDto msg = new();
                            msg.Id = oneMessage.ID_CONVERSATION_LIGNE.ToString();
                            msg.Role = "user";
                            //msg.Content = oneMessage.QUESTION;
                            msg.Model = oneMessage.MODELE!;
                            msg.IsUser = true;
                            msg.Text = oneMessage.QUESTION;
                            msg.CreatedAt = oneMessage.DATE;
                            lstMsg.Add(msg);

                            MessageDto msg2 = new();
                            msg2.Id = oneMessage.ID_CONVERSATION_LIGNE.ToString();
                            msg2.Role = "assistant";
                            //msg2.Content = oneMessage.REPONSE;
                            msg2.Model = oneMessage.MODELE!;
                            msg2.IsUser = false;
                            msg2.Text = oneMessage.REPONSE;
                            msg2.CreatedAt = oneMessage.DATE;
                            lstMsg.Add(msg2);
                        }
                        conv.Messages = lstMsg;
                    }

                    result.Add(conv);

                }
                return result;
            }
            return null;
        }

        public async Task<ConversationDto?> GetConversation(Guid IdConv, IDT_CONVERSATIONService dt_conversationService)
        {
            var oneConv = await dt_conversationService.GetById_Async(IdConv);

            if (oneConv != null)
            {
                ConversationDto conv = new();

                conv.Id = oneConv.ID_CONVERSATION.ToString();
                conv.IdWorkForce = oneConv.ID_WORK_FORCE.ToString();
                conv.TypeConv = oneConv.TypeConv;
                conv.Date = oneConv.DATE_START;
                conv.Title = oneConv.LIBELLE;

                if (oneConv.DT_CONVERSATION_LIGNEs != null && oneConv.DT_CONVERSATION_LIGNEs.Count > 0)
                {
                    var lstMessageOrder = oneConv.DT_CONVERSATION_LIGNEs.Where(m => m.IsEnabled == true).OrderBy(c => c.DATE).ToList();
                    var lstMsg = new List<MessageDto>();

                    foreach (var oneMessage in lstMessageOrder!)
                    {
                        MessageDto msg = new();
                        msg.Id = oneMessage.ID_CONVERSATION_LIGNE.ToString();
                        msg.Role = "user";
                        //msg.Content = oneMessage.QUESTION;
                        msg.Model = oneMessage.MODELE!;
                        msg.IsUser = true;
                        msg.Text = oneMessage.QUESTION;
                        msg.CreatedAt = oneMessage.DATE;
                        lstMsg.Add(msg);

                        MessageDto msg2 = new();
                        msg2.Id = oneMessage.ID_CONVERSATION_LIGNE.ToString();
                        msg2.Role = "assistant";
                        //msg2.Content = oneMessage.REPONSE;
                        msg2.Model = oneMessage.MODELE!;
                        msg2.IsUser = false;
                        msg2.Text = oneMessage.REPONSE;
                        msg2.CreatedAt = oneMessage.DATE;
                        lstMsg.Add(msg2);
                    }
                    conv.Messages = lstMsg;
                }

                return conv;
            }

            return null;
        }


        public async Task<MessageDto> EnvoiRequete_LLM(SendMessageRequest requete, IDT_CONVERSATIONService dt_conversationService, IDT_CONVERSATION_LIGNEService dt_conversation_ligneService, IDT_WORK_FORCEService dt_work_forceService)
        {
            var lst = new List<ChatMessage>();
            var message = new ChatMessage();
            message.Role = "user";
            message.Content = requete.Text;
            lst.Add(message);
            //Guid idConversation = Guid.NewGuid();
            //Guid IdWorkForce = Guid.Empty;
            //bool isNewConversation = true;
            //DT_WORK_FORCE_DTO? wf = new();

            /*
            if (requete.ConversationId != null && requete.ConversationId != "" && requete.ConversationId != Guid.Empty.ToString())
            {
                //idConversation = Guid.Parse(requete.ConversationId);
                isNewConversation = false;
            }
            */

            /*
            if (requete.IdWorkForce != null && requete.IdWorkForce != "" && requete.IdWorkForce != Guid.Empty.ToString())
            {
                IdWorkForce = Guid.Parse(requete.IdWorkForce);
                wf = await dt_work_forceService!.GetById_Async(IdWorkForce!);
            }
            */
            int i = 0;
            bool isDoc = requete.Documents64.Count>0;
            StringBuilder sb = new();
            foreach (var docBase64 in requete.Documents64)
            {
                var bytes = Convert.FromBase64String(docBase64);
                var name = requete.Documents[i];
                var s = ToolsServices.FilesService.ExtractTextFromBytes(bytes, name);
                sb.AppendLine(s);
                // tu traites le fichier ici : indexation, stockage, etc.
                i++;
            }

            // On injecte le contenu des documents
            if (isDoc)
            {
                lst[0].Content += $"\nVoici le contenu des documents joints :\n {sb.ToString()} \n Fin des documents";
            }

            if(requete.Context != "")
            {
                lst[0].Content += $"\nVoici l'historique de la conversation :\n {requete.Context}\n Fin de l'historique de la conversation";
            }

            var (b, reponse, model) = await Services.ChatService.SendMessageAsync(ModelsUseCases.TypeUseCase.LLM, lst, "", false);
            //bool isCreatedSuccess = true;
            if (b)
            {
                var isOk = await SaveMessage(requete, dt_conversationService, dt_conversation_ligneService, dt_work_forceService,model,reponse);
                /*
                // Créer une nouvelle conversation 
                if (isNewConversation)
                {
                    DT_CONVERSATION_DTO item = new();
                    item.ID_CONVERSATION = idConversation;
                    item.LIBELLE = requete.Text.Length <= 50 ? requete.Text : requete.Text.Substring(0, 47) + "...";
                    item.DATE_START = DateTime.Now;
                    item.SystemDateCreated = DateTime.Now;
                    item.SystemDateUpdated = DateTime.Now;
                    item.IsEnabled = true;
                    item.TypeConv = "LLM";
                    item.ID_WORK_FORCE = IdWorkForce;
                    item.DT_WORK_FORCE = wf;

                    isCreatedSuccess = await dt_conversationService.Create_Async(item);
                }
                // Créer une nouvelle conversation-ligne
                if (isCreatedSuccess)
                {
                    DT_CONVERSATION_LIGNE_DTO ligne = new();
                    ligne.ID_CONVERSATION_LIGNE = Guid.NewGuid();
                    ligne.ID_CONVERSATION = idConversation;
                    ligne.DATE = DateTime.Now;
                    ligne.QUESTION = requete.Text;
                    ligne.REPONSE = s;
                    ligne.MODELE = m;
                    ligne.SystemDateCreated = DateTime.Now;
                    ligne.SystemDateUpdated = DateTime.Now;
                    ligne.IsEnabled = true;

                    await dt_conversation_ligneService.Create_Async(ligne);
                }
                */

            }

            MessageDto rep = new();
            rep.Id = Guid.NewGuid().ToString();
            rep.Text = reponse;
            rep.Role = "assistant";
            rep.Model = model;
            rep.CreatedAt = DateTime.Now;

            return rep;// "Réponse du service ChatRoomService";
        }

        public async Task<MessageDto> EnvoiRequete_RAG(SendMessageRequest requete, IDT_CONVERSATIONService dt_conversationService, IDT_CONVERSATION_LIGNEService dt_conversation_ligneService, IDT_WORK_FORCEService dt_work_forceService)
        {

            //var lst = new List<ChatMessage>();
            //var message = new ChatMessage();
            Guid idConversation = Guid.NewGuid();
            Guid IdWorkForce = Guid.Empty;
            //message.Role = "user";
            //message.Content = requete[0];
            //lst.Add(message);
            //bool isNewConversation = true;
            DT_WORK_FORCE_DTO? wf = new();

            /*
            if (requete.ConversationId != null && requete.ConversationId != "" && requete.ConversationId != Guid.Empty.ToString())
            {
                //idConversation = Guid.Parse(requete.ConversationId);
                isNewConversation = false;
            }
            */

            /*
            if (requete.IdWorkForce != null && requete.IdWorkForce != "" && requete.IdWorkForce != Guid.Empty.ToString())
            {
                IdWorkForce = Guid.Parse(requete.IdWorkForce);
                wf = await dt_work_forceService!.GetById_Async(IdWorkForce!);
            }
            */

            Services.Domain domain = DomainExtensions.GetDomainByCollectionName(requete!.Domain!);
            int i = 0;
            bool isDoc = requete.Documents64.Count > 0;

            foreach (var docBase64 in requete.Documents64)
            {
                var bytes = Convert.FromBase64String(docBase64);
                var name = requete.Documents[i];
                var s = ToolsServices.FilesService.ExtractTextFromBytes(bytes, name);
                await RAGService.SaveDocumentAsync(bytes, name, domain);

                i++;
            }



            var (b, reponse, model) = await RAGService.RechercheDansDocuments(domain, requete.Text, "", false);

            //bool isCreatedSuccess = true;
            if (b)
            {
                var isOk = await SaveMessage(requete, dt_conversationService, dt_conversation_ligneService, dt_work_forceService, model, reponse);
                /*

                // Créer une nouvelle conversation 
                if (isNewConversation)
                {
                    DT_CONVERSATION_DTO item = new();
                    item.ID_CONVERSATION = idConversation;
                    item.LIBELLE = requete.Text.Length <= 50 ? requete.Text : requete.Text.Substring(0, 47) + "...";
                    item.DATE_START = DateTime.Now;
                    item.SystemDateCreated = DateTime.Now;
                    item.SystemDateUpdated = DateTime.Now;
                    item.IsEnabled = true;
                    item.TypeConv = "RAG";
                    item.ID_WORK_FORCE = IdWorkForce;
                    item.DT_WORK_FORCE = wf;

                    isCreatedSuccess = await dt_conversationService.Create_Async(item);
                }
                // Créer une nouvelle conversation-ligne
                if (isCreatedSuccess)
                {
                    DT_CONVERSATION_LIGNE_DTO ligne = new();
                    ligne.ID_CONVERSATION_LIGNE = Guid.NewGuid();
                    ligne.ID_CONVERSATION = idConversation;
                    ligne.DATE = DateTime.Now;
                    ligne.QUESTION = requete.Text;
                    ligne.REPONSE = s;
                    ligne.MODELE = m;
                    ligne.SystemDateCreated = DateTime.Now;
                    ligne.SystemDateUpdated = DateTime.Now;
                    ligne.IsEnabled = true;
                    ligne.DomainRAG = requete.Domain;

                    await dt_conversation_ligneService.Create_Async(ligne);
                }
                */

            }

            MessageDto rep = new();
            rep.Id = Guid.NewGuid().ToString();
            rep.Text = reponse;
            rep.Role = "assistant";
            rep.Model = model;
            rep.CreatedAt = DateTime.Now;

            return rep;// "Réponse du service RAGService";
        }

        private async Task<bool> SaveMessage(SendMessageRequest requete, IDT_CONVERSATIONService dt_conversationService, IDT_CONVERSATION_LIGNEService dt_conversation_ligneService, IDT_WORK_FORCEService dt_work_forceService, string m, string r)
        {
            try
            {


                // Créer une nouvelle conversation 
                var isCreatedSuccess = true;
                var idConversation = Guid.NewGuid();
                if (requete.IsNewConversation)
                {
                    Guid IdWorkForce = Guid.Empty;
                    DT_WORK_FORCE_DTO? wf = new();
                    if (requete.IdWorkForce != null && requete.IdWorkForce != "" && requete.IdWorkForce != Guid.Empty.ToString())
                    {
                        IdWorkForce = Guid.Parse(requete.IdWorkForce);
                        wf = await dt_work_forceService!.GetById_Async(IdWorkForce!);
                    }

                    DT_CONVERSATION_DTO item = new();
                    item.ID_CONVERSATION = Guid.Parse(requete.ConversationId);
                    item.LIBELLE = requete.Text.Length <= 150 ? requete.Text : requete.Text.Substring(0, 147) + "...";
                    item.DATE_START = DateTime.Now;
                    item.SystemDateCreated = DateTime.Now;
                    item.SystemDateUpdated = DateTime.Now;
                    item.IsEnabled = true;
                    item.TypeConv = requete.Mode.ToUpper();
                    item.ID_WORK_FORCE = IdWorkForce;
                    item.DT_WORK_FORCE = wf;

                    isCreatedSuccess = await dt_conversationService.Create_Async(item);
                }
                // Créer une nouvelle conversation-ligne
                if (isCreatedSuccess)
                {
                    string resumeDocs = "";
                    if(requete.Documents.Count>0)
                        resumeDocs = string.Join("\n", requete.Documents);


                    DT_CONVERSATION_LIGNE_DTO ligne = new();
                    ligne.ID_CONVERSATION_LIGNE = Guid.NewGuid();
                    ligne.ID_CONVERSATION = Guid.Parse(requete.ConversationId); 
                    ligne.DATE = DateTime.Now;
                    ligne.QUESTION = requete.Documents.Count > 0 ? requete.Text + " : " + resumeDocs : requete.Text;
                    ligne.REPONSE = r;
                    ligne.MODELE = m;
                    ligne.DomainRAG = requete.Domain;
                    ligne.SystemDateCreated = DateTime.Now;
                    ligne.SystemDateUpdated = DateTime.Now;
                    ligne.IsEnabled = true;

                    await dt_conversation_ligneService.Create_Async(ligne);
                }

                return true;
            }
            catch (Exception ex)
            {
                // Log the exception (you can use a logging framework here)
                Console.WriteLine($"Error saving message: {ex.Message}");
                return false;
            }
        }
    }
}