import calibre_plugins.ai_metadata.config as cfg
import calibre_plugins.ai_metadata.api.anything_llm_api as AllmAPI
import json

## for debugging
DEBUG_ALLM = False

class AnythingLLM():
    
    def __init__(self, progress_reporter=False):
        
        self.AI_PLATFORM = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_AI_PLATFORM]
        self.API_URL = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_PLATFORM_URL] + '/api/v1'
        self.API_KEY = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_PLATFORM_API_KEY]
        self.WORKSPACE = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_PLATFORM_WORKSPACE]
        # DELETED self.PROMPT_ENGINEERING = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_PROMPT_ENGINEERING]
        self.PROMPT_ENGINEERING = ''
        self.SUMMARY_ENGINEERING = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_SUMMARY_ENGINEERING]
        self.PROMPT_MODE = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_PROMPT_MODE]
        self.CONTEXT_MODE = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_CONTEXT_MODE]
        
        ## instanciate the API
        self._API = AllmAPI.AnythingLLM_API(self.API_URL, self.API_KEY, self.WORKSPACE, self.CONTEXT_MODE, progress_reporter)
        
        ## if debug mode is on, then turn it on in the API
        if DEBUG_ALLM == True:
            self._API.debug_reponse()
        
        if self.PROMPT_MODE == "Accuracy":
            try:
                self.ADVANCED_QUESTIONS = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_ADVANCED_QUESTIONS]
            except Exception as e:
                self.ADVANCED_QUESTIONS = []
    
    def authenticate(self):
        return self._API.authenticate()

    def compile_accuracy_questions(self):
        if self.ADVANCED_QUESTIONS != False:
            if len(self.ADVANCED_QUESTIONS) > 0:
                return self.ADVANCED_QUESTIONS

    def ask_ai_single_prompt(self,file_name):
        ## send the prompt in one go
        PAYLOAD = {}
        if self.PROMPT_MODE == "Summarise":
            PAYLOAD['message'] = f"Please analyse the book or document '{file_name}'. Extract the following information: - Title: The title of the book or document - Author: The author(s) - Summary: A concise, well-written summary of the entire content in your own words "+ self.SUMMARY_ENGINEERING +". Output only a valid JSON object using this exact structure: { \"Title\": \"Title of the book or document\", \"Author\": \"Author(s) name(s)\", \"Summary\": \"Your summary here.\" } If any information is unavailable or cannot be determined, return \"Not Available\" for that field. Do not include anything outside the JSON (no extra text, notes, or formatting).".replace("   ","").replace("  ","")
        else:
            PAYLOAD['message'] = f"Please analyse the book or document '{file_name}' for information. I require the ISBN, Publisher, PublicationDate, Author, Title, Language and Genre. Summary: Please provide a concise, well-written summary of the entire content in your own words "+ self.SUMMARY_ENGINEERING +". Provide the summary in a single field, do not split it into multiple fields. Don't source the publication date from the metadata as it is often wrong. Return the response in Json Format, only provide the Json as the Response. If any information is unavailable or cannot be determined, return \"Not Available\". Use this structure: { \"ISBN\": \"\", \"Publisher\": \"\", \"PublicationDate\": \"\", \"Author\": \"\", \"Title\": \"\", \"Language\": \"\", \"Genre\": \"\", \"Summary\": \"\" }".replace("   ","").replace("  ","")
        PAYLOAD['mode'] = "query"
        PAYLOAD['userId'] = 1
        PAYLOAD['reset'] = 'false'
        
        return self._API.send_ai_question(PAYLOAD, file_name, "")

    def ask_ai_multiple_questions(self,file_name):
        returned_dict = {}
        ## the mode is accuracy, hybrid or tag, break the prompt into individual questions and ask them one by one to maximise RAG efficiency
        questions = self.compile_accuracy_questions()
        for question in questions:
            PAYLOAD = {}
            PAYLOAD['message'] = f"Please analyse the book or document '{file_name}' for information. {question}. Return the response in Json Format, only provide the Json as the Response. If any information is unavailable or cannot be determined, return \"Not Available\".".replace("   ","").replace("  ","")
            PAYLOAD['mode'] = "query"
            PAYLOAD['userId'] = 1
            PAYLOAD['reset'] = 'false'
            
            returned_payload = self._API.send_ai_question(PAYLOAD, file_name, question)
            if returned_payload != None:
                returned_dict = {**returned_dict, **returned_payload}
        
        return returned_dict
        
    def ask_ai_questions(self,file_name):
        
        if self.PROMPT_MODE == "Efficiency" or self.PROMPT_MODE == "Summarise":
            return self.ask_ai_single_prompt(file_name)
        else:
            return self.ask_ai_multiple_questions(file_name)
            
    def send_chat_message_to_ai(self,ebook_location):
       
        # check see if the workplace exists
        self._API.check_workspace_exists()
        # upload the document
        self._API.upload_document_to_workspace(ebook_location)
            
        ## ask the a.i. bot the questions on the document
        file_name = self._API.strip_filename_from_path(ebook_location)
        returned_dict = self.ask_ai_questions(file_name)
        
        if DEBUG_ALLM != True:
            ## if we have got the data we now cleanup
            self._API.cleanup()
        
        return returned_dict

#authenticate()
