import os
import json
from django.conf import settings
from django.utils.translation import get_language
import re
import sqlite3
import shutil
import traceback
from admin_base.functions import database, traceback_error, SpinnerWithMessage
from admin_base.tbot.llms import tbot, tbot_backup, tbot_advanced
from admin_base.tbot.utils import translation_check, translation_logger
from termcolor import colored
import time
import logging

translation_logger()

name_pattern = re.compile(r'^(?P<name>.+)_content_index\.json$')

def translate_file(file_path, language_code, bots):
    """
    Translate the titles and keys in the JSON file while keeping placeholders like {{SHOW}} intact.
    """
    
    llm_model = bots[0]
    
    with open(file_path, 'r', encoding='utf-8') as file:
        data = json.load(file)
    
    def translate_text(text, json_position):
        # Extract functions like {{SHOW}}
        functions = re.findall(r'{{.*?}}', text)
        
        # Remove functions for translation
        text_no_functions = re.sub(r'{{.*?}}', '', text)
        
        for lang_code, lang_name in settings.LANGUAGES:
            if lang_code == language_code:
                language = lang_name
                break
        
        if json_position == 'accordition_title':
            prompt = f"""
            You are an experienced translator with expertise in {language} and a deep understanding of web design and user interface terminology. 
            Your task is to translate the phrase "{text_no_functions}" into {language}, ensuring that it remains suitable for use as an accordion section title in a backend user interface. 

            Guidelines:
            1. The accordion title should be concise, clear, and representative of the section it refers to, allowing users to easily understand what content is under that section when expanded.
            2. Do not include any unnecessary characters, punctuation, or explanations.
            3. Ensure the translation remains simple and direct, as it will appear as a clickable title in the backend UI.
            4. Translate the text naturally into {language} while keeping it culturally relevant and user-friendly for backend users.

            The output should only include the translated accordion title in {language} with no additional formatting or punctuation.
            """
                
        elif json_position == 'input_title':
            prompt = f"""
            You are a skilled translator with expertise in {language} and a deep understanding of web design and user interface terminology. 
            Your task is to translate the phrase "{text_no_functions}" into {language}, ensuring that it works effectively as a field title (label) above an input box in a backend user interface.

            Guidelines:
            1. The field title should clearly describe the input required from the user, making it intuitive and easy to understand for backend users.
            2. Avoid long, complicated phrases. Keep the translation clear and concise.
            3. Do not include any unnecessary characters, punctuation, or explanations.
            4. Ensure that the translation reflects the field's purpose, without altering the intent of the original text.
            5. Translate the text naturally into {language}, ensuring cultural appropriateness and clarity for backend users.

            The output should only include the translated field title in {language} with no additional formatting or punctuation.
            """
            
        else:
            raise Exception
    
        translated_text_unformated = llm_model.generate_response(prompt)
        
        # Translated String Check
        text_check_status, translated_text = translation_check(translated_text_unformated, text_no_functions, language_code, bots)
        
        if functions:
            translated_text = f"{translated_text} {functions[0]}"
            
        else:
            pass
            
        return translated_text
    
    # Translate keys (e.g., "Field Demo {{SHOW}}")
    translated_data = {}
    
    for key, value in data.items():
        # Title
        translated_key = translate_text(key, 'accordition_title') if isinstance(key, str) else key
        
        if isinstance(value, list):
            
            translated_data[translated_key] = []
            
            for item in value:
                # Single Value title
                if "title" in item:
                    item["title"] = translate_text(item["title"], 'input_title')
                    translated_data[translated_key].append(item)
                
                # Mult Value title
                else:
                    
                    for mult_value_field in item:
                        mult_value_label_translation = translate_text(mult_value_field, 'input_title')

                        mult_value_list = {f"{mult_value_label_translation}": [
                            
                        ]}
                        
                        for mult_value in item[mult_value_field]:
                            if "title" in mult_value:
                                mult_value["title"] = translate_text(mult_value["title"], 'input_title')
                                
                            mult_value_list[mult_value_label_translation].append(mult_value)
                            
                        translated_data[translated_key].append(mult_value_list)                    

        else:
            translated_data[translated_key] = value
    
    # Save the translated file
    with open(file_path, 'w', encoding='utf-8') as file:
        json.dump(translated_data, file, indent=4, ensure_ascii=False)
     
def content_index_translate(language_code, bots):
    """
    Translate content index files by creating new files with language code suffixes. If the translation
    already exists, it avoids re-translating unless a new language code is provided.
    Example: 'home_content_index.json' becomes 'home_ar_content_index.json'.
    
    Args:
        language_code (str): The language code to translate to.
        bots (list): Additional translation tools or parameters.
    """
    base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    folder_path = os.path.join(base, "cms", "content_index")
    en_folder_path = os.path.join(folder_path, "en")
    lang_folder_path = os.path.join(folder_path, language_code)

    # Check if the language folder exists
    if not os.path.isdir(lang_folder_path):
        # Copy the entire 'en' folder to the new language folder
        shutil.copytree(en_folder_path, lang_folder_path)
        files_to_translate = os.listdir(lang_folder_path)
    else:
        # Compare files in 'en' and language folder
        en_files = set(os.listdir(en_folder_path))
        lang_files = set(os.listdir(lang_folder_path))
        
        files_to_translate = list(en_files - lang_files)
        
        if not files_to_translate:
            print(colored("Everything is translated in Content Index Folder\n", 'yellow'))
            return
        
        # Copy missing files from 'en' to language folder
        for file_name in files_to_translate:
            shutil.copy(os.path.join(en_folder_path, file_name), os.path.join(lang_folder_path, file_name))

    # Translate files
    if files_to_translate:
        print(colored("\nStarting translation of content index files...\n", "blue"))
        errored_files = []
        
        for file_name in files_to_translate:
            file_path = os.path.join(lang_folder_path, file_name)
            spinner = SpinnerWithMessage("Creating & Translating file: " + colored(file_name, 'dark_grey'))
            spinner.start()
            
            try:
                # Translate the file content
                translate_file(file_path, language_code, bots)
                logging.info(f"Succesfully translated {file_name}.")
                spinner.stop(f"Succesfully translated {colored(file_name, 'cyan')}.", 'success')
            except:
                logging.error(f"Errors raised when translating {file_name}.")
                spinner.stop(f"Errors raised when translating {file_name}.", 'error')
                traceback_error(detailed=True)

        if errored_files:
            print(colored("\nTranslation of content index files completed.\n", 'light_green'))
            print(colored(f"Files with errors: {errored_files}\n", 'red'))
        else:
            print(colored("\nTranslation of content index files completed successfully.\n", 'light_green'))
    else:
        print(colored("Nothing needs to be translated in Content Index Folder\n", 'yellow'))
            
def translate_database(language_code, bots):
    """
    Create a copy of the cms_content.sqlite file and translate all text fields in all tables.
    The new file will be named cms_content_{language_code}.sqlite.

    Args:
        language_code (str): The language code for the translation (e.g., "ar", "fr").
    """
    
    print(colored('\nStarting database translation...\n', 'blue'))
    
    # Unpack bots
    llm_model = bots[0]
    
    # Define file paths
    storage_dir = os.path.join(os.path.dirname(__file__), "storage")
    original_file = os.path.join(storage_dir, "content_en.sqlite3")
    translated_file = os.path.join(storage_dir, f"content_{language_code}.sqlite3")
    
    if os.path.exists(translated_file):
        print(colored("Database already translated\n", 'yellow'))
        return

    # Step 1: Copy the original database file
    try:
        shutil.copy(original_file, translated_file)
        #print(f"Copied {original_file} to {translated_file}")
    except Exception as e:
        print(f"Error copying database file: {e}")
        return
    
    spinner = SpinnerWithMessage("Translating database content...")

    spinner.start()
    
    # Step 2: Connect to the copied database
    try:
        conn = sqlite3.connect(translated_file)
        cursor = conn.cursor()

        # Step 3: Get all table names in the database
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
        tables = [row[0] for row in cursor.fetchall()]

        # Step 4: Iterate over each table
        for table in tables:
            
            #spinner.update("Translating database content: " + colored(table, 'cyan'))
            spinner.update("Translating database content: " + colored(table, 'dark_grey'))
            
            cursor.execute(f"PRAGMA table_info({table});")
            columns = [col[1] for col in cursor.fetchall()]  # Column names

            # Fetch all rows from the table
            cursor.execute(f"SELECT * FROM {table}")
            rows = cursor.fetchall()

            for row in rows:
                # Step 5: Iterate over each field in the row
                for col_index, col_name in enumerate(columns):
                    original_value = row[col_index]

                    # Translate only if the value is a non-empty string
                    if isinstance(original_value, str) and original_value.strip():
                        # Skip file names for images or videos
                        if any(
                            original_value.lower().endswith(ext)
                            for ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv']
                        ):
                            continue

                        # Translate text
                        try:
                            for lang_code, lang_name in settings.LANGUAGES:
                                if lang_code == language_code:
                                    language = lang_name
                                    break

                            prompt = f"""
                            You’re a skilled translator with expertise in {language} and a deep understanding of web design terminology. 
                            You specialize in providing precise translations for website content to ensure 
                            clarity and cultural relevance. Your task is to translate the sentence/paragraph "{original_value}" into {language}. 
                            Keep in mind that you may translate the phrase into more characters or words than it originally contains to better match the context. 
                            Output only the translated phrase in {language} with no special characters or punctuation.
                            """
                        
                            translated_text_unformated = llm_model.generate_response(prompt)
                            text_check_status, translated_text = translation_check(translated_text_unformated, original_value, lang_code, bots)

                            #print(f"Translating in {table} | {col_name}: {original_value} -> {translated_text}")
                            
                            # Update the database field
                            database.update(
                                db_path=translated_file,
                                table=table,
                                column=col_name,
                                new_value=translated_text,
                                do_log=False,
                            )
                            
                        except Exception as translate_error:
                            #print(f"Error translating field in table {table}, column {col_name}: {translate_error}")
                            pass
            
            spinner.stop("Translating database content: " + colored(table, 'cyan'))
        
        # Commit the changes
        conn.commit()

    except sqlite3.Error as e:
        print("error")
    finally:
        if conn:
            print(colored('\nDatabase translation completed successfully.\n', 'light_green'))
            conn.close()

def translate_labels(language_code, bots):
    """
    Translate labels in the content index folder and save them to a JSON file.
    
    Args:
        language_code (str): The language code to translate to.
        bots (list): Additional translation tools or parameters.
    """
    llm_model = bots[0]
    
    print(colored("\nStarting translation of sidebar labels...\n", 'blue'))
    
    base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    folder_path = os.path.join(base, "cms", "content_index", language_code)
    
    locale_folder = os.path.join(base, "cms", "locale")
    
    # Check if the locale folder exists, create if not
    if not os.path.exists(locale_folder):
        os.makedirs(locale_folder)
    
    # Check if Language folder exists    
    language_dir = os.path.join(locale_folder, 'ar')
    
    if os.path.exists(language_dir):
        output_file = os.path.join(language_dir, f"labels_{language_code}.json")
        
    else:
        os.mkdir(language_dir)
        output_file = os.path.join(language_dir, f"labels_{language_code}.json")
    
    if os.path.exists(output_file):
        print(colored("Sidebar labels already translated\n", 'yellow'))
        return
    
    # List to store translation data
    translations = []
    
    # Loop through all files in the language folder
    for file_name in os.listdir(folder_path):
        
        # Check if the file name matches the pattern
        match = name_pattern.match(file_name)
        if match:
            preview_name = match.group('name')
            name = f"{match.group('name').capitalize()} Page"
            
            language = "Arabic"
            
            prompt = f"""
            You are an experienced translator with expertise in {language} and a deep understanding of web design and user interface terminology. 
            Your task is to translate the phrase "{name}" into {language}, ensuring that it remains suitable for use as an accordion section title in a backend user interface. 

            Guidelines:
            1. The accordion title should be concise, clear, and representative of the section it refers to, allowing users to easily understand what content is under that section when expanded.
            2. Do not include any unnecessary characters, punctuation, or explanations.
            3. Ensure the translation remains simple and direct, as it will appear as a clickable title in the backend UI.
            4. Translate the text naturally into {language} while keeping it culturally relevant and user-friendly for backend users.

            The output should only include the translated accordion title in {language} with no additional formatting or punctuation.
            """
            
            translated_label_raw = llm_model.generate_response(prompt)
            
            status, translated_label = translation_check(translated_label_raw, name, language_code, bots)
            
            # Add to translations list
            translations.append({"original": preview_name, "translated": translated_label})
    
    with open(output_file, 'w', encoding='utf-8') as json_file:
        json.dump(translations, json_file, indent=4, ensure_ascii=False)
        
    print(colored('\nSidebar labels transaltion completed successfully.\n', 'light_green'))
    
        
def translate_app(language_code):
    """
    Parent function to process all JSON files in the folder.
    - Create new files with the language code suffix.
    - Translate their content while preserving placeholders like {{SHOW}}.
    """ 
    
    # Translate Content Index Files         
    try:
        # Model Initiation
        print(colored("\nStarting model initiation...\n", 'blue'))
        try:
            bots = tbot(), tbot_backup(), tbot_advanced()
            logging.info(f"Main Bot: {bots[0].model}")
            logging.info(f"Backup Bot: {bots[1].model}")
            logging.info(f"Advanced Bot: {bots[2].model}")
            print(colored('\nModel initiated successfully.\n', 'light_green'))
            
            # Translate content index folder's files
            content_index_translate(language_code, bots)
            
        except:
            traceback_error()
            return False
                
        # Translate database
        translate_database(language_code, bots)
        
        # Translate sidebar labels
        translate_labels(language_code, bots)
        
    except:
        print("Error processing files")
        traceback.print_exc()
    
def remove(language_code):
    
    cms_dir = os.path.join(os.getcwd(), 'cms')
    
    # Remove Locale Folder content
    locale_folder = os.path.join(cms_dir, "locale", language_code)
    if os.path.exists(locale_folder):
        shutil.rmtree(locale_folder)
        
    # Remove Content Index folder content
    content_index_folder = os.path.join(cms_dir, "content_index", language_code)
    if os.path.exists(content_index_folder):
        shutil.rmtree(content_index_folder)
        
    # Remove Database content
    database_file = os.path.join(cms_dir, "storage", f'content_{language_code}.sqlite3')
    if os.path.exists(database_file):
        os.remove(database_file) 