using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MercatorUi;
using MercatorApi;
using MercatorExtensions;

// <CompileWithRoslyn />

namespace MyAssembly
{
    public static class ChatGPT
    {
        private const string tutosCollectionName = "Tutos";

        public static async Task SearchInTutos()
        {
            MercatorAI.FactoryOpenAI factoryOpenAI = new MercatorAI.FactoryOpenAI();
            MercatorAI.Interfaces.IOpenAiEmbeddingGeneratorClient openAiEmbeddingGeneratorClient = factoryOpenAI.CreateOpenAiEmbeddingGeneratorClient<string>("text-embedding-3-small"out string error);
            if (!string.IsNullOrEmpty(error))
            {
                Dialogs.Stop("Impossible d'initialiser le générateur d'embeddings d'OpenAI : " + error);
                return;
            }

            MercatorAI.FactoryQdrant factoryQdrant = new MercatorAI.FactoryQdrant();
            MercatorAI.Interfaces.IQdrantClient qdrantClient = factoryQdrant.CreateQdrantClient("http://192.168...:6334"out error);
            if (!string.IsNullOrEmpty(error))
            {
                Dialogs.Stop("Impossible d'initialiser le client Qdrant : " + error);
                return;
            }

            MercatorUi.Wait.WaitStatic.WaitWindow(Api.Iif_langue(Globals.Langue, IifLangueEnum.AIisThinking));

            if (!await qdrantClient.CollectionExistsAsync(tutosCollectionName))
            {
                qdrantClient.Dispose();
                MercatorUi.Wait.WaitStatic.WaitClear();
                Dialogs.Stop($"La collection \"{tutosCollectionName}\" n'existe pas sur le serveur Qdrant !");
                return;
            }

            MercatorUi.Forms.Other.ChatForm chatForm = MercatorUi.Forms.Other.ChatForm.SimpleOpenAiChat("gpt-4o", tutosCollectionName, systemMessage: null, question: ""false, chatOptions: null, standardStreamingAction: MercatorUi.Forms.Other.ChatForm.StandardStreamingActionEnum.RawStreamShow);
            MercatorUi.Wait.WaitStatic.WaitClear();
            if (chatForm == null)
            {
                qdrantClient.Dispose();
                return;
            }
            chatForm.Disposed += (s, e) =>
            {
                qdrantClient.Dispose();
            };

            MercatorUi.Forms.Other.ChatForm.BeforeAskEventHandler beforeAskEventHandler = null;
            beforeAskEventHandler = (s, e) =>
            {
                if (string.IsNullOrWhiteSpace(chatForm.TextBoxQuestion.Text))
                {
                    _Divers.FocusError(chatForm.TextBoxQuestion);
                    return;
                }
                (double? score, DocChunk docChunk)[] hits = null;
                MercatorUi.Wait.WaitStatic.WaitWindowBaseThread(Api.Iif_langue(Globals.Langue, IifLangueEnum.AIisThinking));
                MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync exclusiveBackgroundWorkerAsync = new MercatorUi._BaseClasses.ExclusiveBackgroundWorkerAsync(async () =>
                {
                    float[] questionAsVectors = await openAiEmbeddingGeneratorClient.GenerateEmbeddingAsync(chatForm.TextBoxQuestion.Text);
                    hits = await qdrantClient.ClientSearchAsync<GuidDocChunk>(tutosCollectionName, questionAsVectors, top: 5);
                }, formWhereToCenterLoadingCircle: chatForm);
                MercatorUi.Wait.WaitStatic.WaitClearBaseThread();
                if (exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork != null)
                {
                    Dialogs.Stop(exclusiveBackgroundWorkerAsync.ExceptionDuringDoWork.Message, chatForm);
                    return;
                }
                if ((hits == null) || !hits.Any())
                {
                    Dialogs.Stop("Aucune correspondance trouvée dans la documentation !", chatForm);
                    return;
                }

                var sb = new StringBuilder();
                foreach ((double? score, DocChunk docChunk) hit in hits)
                {
                    sb.AppendLine(hit.docChunk.Content);
                }

                chatForm.SimpleChatSystemMessage = "Tu es un assistant. Réponds en t'appuyant uniquement sur le CONTEXTE qui est extrait de tutos expliquant certaines procédure comptables dans notre entreprise. Si l'info n’y est pas, dis-le clairement. \nCONTEXTE:\n" + sb;
                chatForm.BeforeAsk -= beforeAskEventHandler; // SimpleChatSystemMessage uniquement lors de la première interaction dans le chat
            };
            chatForm.BeforeAsk += beforeAskEventHandler;
        }     
    }

}