from __future__ import unicode_literals, division, absolute_import, print_function

__license__   = 'GPL v3'
__copyright__ = '2025, Digital Assassins'

from six import text_type as unicode
# Maintain backwards compatibility with older versions of Qt and calibre.
try:
    from qt.core import QLabel, QHBoxLayout, QVBoxLayout, Qt, QGroupBox, QCheckBox, QSpinBox, QComboBox, QLineEdit, QPlainTextEdit
except ImportError:
    from PyQt5.Qt import QLabel, QHBoxLayout, QVBoxLayout, Qt, QGroupBox, QCheckBox, QSpinBox, QComboBox, QLineEdit, QPlainTextEdit
from calibre.gui2.metadata.config import ConfigWidget as DefaultConfigWidget
from calibre.utils.config import JSONConfig
from calibre.constants import CONFIG_DIR_MODE, config_dir
from calibre_plugins.ai_metadata.encode_ascii import ckc_ls
import json
import os

# Pull in translation files for _() strings
try:
    load_translations()
except NameError:
    pass # load_translations() added in calibre 1.9

STORE_NAME = 'Options'
KEY_TIMEOUT_SECS = 'timeoutSecs'
KEY_AI_PLATFORM = 'aiPlatform'
KEY_PLATFORM_URL = 'aiPlatformUrl'
KEY_PLATFORM_API_KEY = 'aiPlatformApiKey'
KEY_PLATFORM_WORKSPACE = 'aiPlatformWorkspace'
KEY_SUMMARY_ENGINEERING = 'aiSummaryEngineering'
KEY_PROMPT_MODE = 'aiPromptMode'
KEY_ADVANCED_QUESTIONS = 'aiAdvancedQuestions'

SUPPORTED_PLATFORMS = {
    0: "AnythingLLM",
    1: "GPT4All",
    2: "OpenWebUI"
}

PROMPT_MODES = {
    0:"Efficiency",
    1:"Accuracy",
    2:"Summarise",
}

DEFAULT_PLATFORM_URLS = {
    "AnythingLLM": "http://127.0.0.1:3001",
    "GPT4All": "http://127.0.0.1:3001",
    "OpenWebUI": "http://127.0.0.1:3001"
}

BLOCK_LIST = {
    "anthropic.com",
    "cohere.com",
    "openai.com",
    "mistral.ai",
    "meta.com",
    "api.google.com"
}

DEFAULT_STORE_VALUES = {
    KEY_TIMEOUT_SECS: 600,
    KEY_AI_PLATFORM: "AnythingLLM",
    KEY_PLATFORM_URL: '',
    KEY_PLATFORM_API_KEY: '',
    KEY_PLATFORM_WORKSPACE: 'CalibreEbooks',
    KEY_SUMMARY_ENGINEERING: 'The Summary must be 4 paragraphs in length. If there is a story, do not provide any spoilers. I love lore, If there is any in the story, provide as much lore from the story as possible in the summary, unless revealing the lore would include a spoiler.',
    KEY_PROMPT_MODE: 'Efficiency',
    KEY_ADVANCED_QUESTIONS: [],
}

# This is where all preferences for this plugin will be stored
plugin_prefs = JSONConfig('plugins/AIMetadata')
PLUGIN_PATH = os.path.join(config_dir, 'plugins')

# Set defaults
plugin_prefs.defaults[STORE_NAME] = DEFAULT_STORE_VALUES

class ConfigWidget(DefaultConfigWidget):
    
    import calibre_plugins.ai_metadata.anything_llm as anythingllm
    
    def create_advanced_questions(self, questions_path):
        try:
            with open(questions_path, "w") as file:
                file.write("I require a field '{ISBN}' Please provide the Book ISBN. ISBNs are normally located on the copyright page of the book. ISBNs are typically 10 or 13 digits long.")
                file.write("\n")
                file.write("I require a field '{Publisher}' Please provide the Publisher of the Book.")
                file.write("\n")
                file.write("I require a field '{PublicationDate}' Please provide the Date of Publication, Provide the earliest date. Don't source the publication date from the metadata as it is often wrong.")
                file.write("\n")
                file.write("I require a field '{Author}' Please provide the book Author.")
                file.write("\n")
                file.write("I require a field '{Title}' Please provide the book title from the context, Do NOT return the filename from the metadata as the Title.")
                file.write("\n")
                file.write("I require a field '{Genre}' Please provide the Genre of the book or Literary Genres this book's content would fit into.")
                file.write("\n")
                file.write("I require a field '{Summary}', Please provide your own Summary of the book. {SumEng}")
                file.write("\n")
            return True
        except Exception as e:
            return e
        
    def get_advanced_questions(self):
        questions_path = PLUGIN_PATH + os.sep + "AIMetadata-Advanced-Questions.txt"        
        try:
            with open(questions_path, "r") as file:
                questions = [line.rstrip() for line in file]        
            questions = [q.replace('{ISBN}', 'ISBN').replace('{Publisher}', 'Publisher').replace('{PublicationDate}', 'Publication Date').replace('{Author}', 'Author').replace('{Title}', 'Title').replace('{Genre}', 'Genre').replace('{Summary}', 'Summary').replace('{SumEng}', str( self.pf_summary_engineering_msg.toPlainText() ).replace("|","").replace("\n","|") ) for q in questions]        
            return questions
            
        except Exception as e:            
            self.create_advanced_questions(questions_path)
            return False
        
    def initialise_advanced_questions(self):
        questions = self.get_advanced_questions()
        if questions == False:
            questions = self.get_advanced_questions()
            if questions == False:
                questions = self.get_advanced_questions()
        return
    
    def __init__(self, plugin):
        DefaultConfigWidget.__init__(self, plugin)
        c = plugin_prefs[STORE_NAME]
        
        '''
        options_group_box = QGroupBox('Platform Options', self)
        options_group_box_layout = QVBoxLayout()
        options_group_box.setLayout(options_group_box_layout)
        self.l.addWidget(options_group_box, self.l.rowCount(), 0, 1, 2)

        other_group_box_layout = QVBoxLayout()
        platform_label = QLabel(_('AI Platform to Communicate with:'), self)
        platform_label.setToolTip(_('Please select your AI Platform of Choice.\n\n'
                             'Currently only AnythingLLM is supported\n'
                             'more Platforms to be added in the future.'))
        other_group_box_layout.addWidget(platform_label)
        self.ai_platform_cb = QComboBox(self)
        
        for sp_id in SUPPORTED_PLATFORMS:
            self.ai_platform_cb.insertItem(sp_id, SUPPORTED_PLATFORMS[sp_id])

        other_group_box_layout.addWidget(self.ai_platform_cb)          
        
        self.pf_url_label = QLabel('Platform URL:')
        self.pf_url_msg = QLineEdit(self)
        self.pf_url_msg.setText( c.get(KEY_PLATFORM_URL, DEFAULT_STORE_VALUES[KEY_PLATFORM_URL]) )
        other_group_box_layout.addWidget(self.pf_url_label)
        other_group_box_layout.addWidget(self.pf_url_msg)        
        
        self.key_label = QLabel('API Key:')
        self.key_msg = QLineEdit(self)
        self.key_msg.setText( c.get(KEY_PLATFORM_API_KEY, DEFAULT_STORE_VALUES[KEY_PLATFORM_API_KEY]) )
        other_group_box_layout.addWidget(self.key_label)
        other_group_box_layout.addWidget(self.key_msg)
        
        self.pf_workspace_label = QLabel('Workspace:')
        self.pf_workspace_msg = QLineEdit(self)
        self.pf_workspace_msg.setText( c.get(KEY_PLATFORM_WORKSPACE, DEFAULT_STORE_VALUES[KEY_PLATFORM_WORKSPACE]) )
        other_group_box_layout.addWidget(self.pf_workspace_label)
        other_group_box_layout.addWidget(self.pf_workspace_msg)
        
        self.pf_summary_engineering_label = QLabel('Summary Engineering:')
        self.pf_summary_engineering_label.setToolTip(_('Provide your own summary engineering.\n\n'
                             'For example tell the AI Model how many paragraphs you want in your summary, if you do not want spoilers\n'
                             'ask for lore, you can even ask the A.I to provide the summary multiple times in multiple languages if so required.'))
        self.pf_summary_engineering_msg = QPlainTextEdit(self)
        self.pf_summary_engineering_msg.setPlainText( c.get(KEY_SUMMARY_ENGINEERING, DEFAULT_STORE_VALUES[KEY_SUMMARY_ENGINEERING]) )
        other_group_box_layout.addWidget(self.pf_summary_engineering_label)
        other_group_box_layout.addWidget(self.pf_summary_engineering_msg)      
        
        prompt_mode_label = QLabel(_('Prompt Mode:'), self)
        prompt_mode_label.setToolTip(_('Please select the Prompt mode.\n\n'
                             'Efficiency sends a single prompt. quicker but less accurate\n'
                             'Accuracy sends each question individually. slower but more accurate.\n'
                             'Summarise asks only for a Summary. Useful for when all you are missing is a summary for each title.'))
        other_group_box_layout.addWidget(prompt_mode_label)
        self.ai_prompt_mode_cb = QComboBox(self)
        
        for pm_id in PROMPT_MODES:
            self.ai_prompt_mode_cb.insertItem(pm_id, PROMPT_MODES[pm_id])
        
        other_group_box_layout.addWidget(self.ai_prompt_mode_cb)
        
        other_group_box_layout.addSpacing(5)
        
        options_group_box_layout.addLayout(other_group_box_layout)
        
        options_group_box_layout.addSpacing(5)
        options_group_box_layout.addStretch(1)
        
        
        for sp_id in SUPPORTED_PLATFORMS:
            if str(SUPPORTED_PLATFORMS[sp_id]) == str( c.get(KEY_AI_PLATFORM, DEFAULT_STORE_VALUES[KEY_AI_PLATFORM]) ):
                self.ai_platform_cb.setCurrentIndex(sp_id)
                
        for pm_id in PROMPT_MODES:
            if str(PROMPT_MODES[pm_id]) == str( c.get(KEY_PROMPT_MODE, DEFAULT_STORE_VALUES[KEY_PROMPT_MODE]) ):
                self.ai_prompt_mode_cb.setCurrentIndex(pm_id)
        '''
        
        
        
        
    def commit(self):
        DefaultConfigWidget.commit(self)
        
        new_prefs = {}
        new_prefs[KEY_AI_PLATFORM] = str( self.ai_platform_cb.itemText(self.ai_platform_cb.currentIndex()) )
        new_prefs[KEY_PLATFORM_URL] = ckc_ls( str( self.pf_url_msg.text() ), DEFAULT_PLATFORM_URLS, str( self.ai_platform_cb.itemText(self.ai_platform_cb.currentIndex()) ) )
        new_prefs[KEY_PLATFORM_API_KEY] = str( self.key_msg.text() )
        new_prefs[KEY_PLATFORM_WORKSPACE] = str( self.pf_workspace_msg.text() )
        new_prefs[KEY_SUMMARY_ENGINEERING] = str( self.pf_summary_engineering_msg.toPlainText() )
        new_prefs[KEY_PROMPT_MODE] = str( self.ai_prompt_mode_cb.itemText(self.ai_prompt_mode_cb.currentIndex()) )
        if self.ai_prompt_mode_cb.itemText(self.ai_prompt_mode_cb.currentIndex()) == "Accuracy":
            # initialise the default advanced questions
            self.initialise_advanced_questions()
        
        new_prefs[KEY_ADVANCED_QUESTIONS] = self.get_advanced_questions()
        
        plugin_prefs[STORE_NAME] = new_prefs
        
        # if not self.anythingllm.authorize:
