let translationDictionary = {};
let elementTranslations = {};
let customElementTranslationInterval;
let domTranslator;
let currentLanguage = getCookie('language');
let sourceLanguage = null;  // This will be fetched dynamically
let dictionaryLoaded = false;
let dictionaryLoadingPromise = null;
let translationQueue = [];
let translationTimer = null;
let iframeObserver = null; // Observer for dynamically added iframes

// Function to get the current page path
function getPagePath() {
    return window.location.pathname;
}

// Function to get a cookie value by name
function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

// Function to set a cookie
function setCookie(name, value, days) {
    const date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    const expires = `expires=${date.toUTCString()}`;
    document.cookie = `${name}=${value};${expires};path=/`;
}

// Fetch source language dynamically
async function fetchSourceLanguage() {
    try {
        const response = await fetch(`https://rubyroid.tech//weblang/websites/8019172b-93c6-4dfa-ba1e-256425430102/languages`);
        if (!response.ok) throw new Error('Failed to fetch languages');
        const languages = await response.json();
        const sourceLang = languages.find(lang => lang.source_language === true);
        if (sourceLang) {
            sourceLanguage = sourceLang.code;
            console.log(`Source language is: ${sourceLanguage}`);
        } else {
            console.warn('Source language not found.');
        }
    } catch (error) {
        console.error('Failed to fetch the source language:', error);
    }
}

// Fetch translation dictionary from API
async function loadTranslationDictionary(pagePath, language) {
    if (language === sourceLanguage) {
        // If the language is the source language, no need to translate.
        return {};
    }

    console.log(`Loading translation dictionary from API for path: ${pagePath} and language: ${language}`);
    try {
        const response = await fetch(`https://rubyroid.tech//weblang/websites/8019172b-93c6-4dfa-ba1e-256425430102/dictionary?page_path=${encodeURIComponent(pagePath)}&language=${encodeURIComponent(language)}`);
        if (!response.ok) throw new Error('Network response was not ok');
        const data = await response.json();
        console.log('Translation dictionary loaded:', data.translations || {});
        return data.translations || {};
    } catch (error) {
        console.error('Failed to load translation dictionary:', error);
        return {};
    }
}

async function loadCustomElementTranslations(pagePath, language) {
    // Avoid redundant API calls if translations are already cached
    if (elementTranslations[pagePath]?.[language]) { return; }

    try {
        const response = await fetch(
          `https://rubyroid.tech//weblang/websites/8019172b-93c6-4dfa-ba1e-256425430102/element_translations?page_path=${encodeURIComponent(pagePath)}&language=${encodeURIComponent(language)}`
        );
        if (!response.ok) throw new Error('Failed to fetch custom element translations');
        const data = await response.json();

        // Cache the translations
        elementTranslations[pagePath] ||= {};
        elementTranslations[pagePath][language] = data.element_translations || [];
    } catch (error) {
        console.error('Failed to load custom element translations:', error);
        elementTranslations[pagePath] ||= {};
        elementTranslations[pagePath][language] = []; // Fallback to empty array
    }
}

// Fetch translation from API in batches
async function fetchTranslationBatch(batch) {
    console.log('Fetching translation for batch:', batch);
    try {
        const response = await fetch(`https://rubyroid.tech//weblang/websites/8019172b-93c6-4dfa-ba1e-256425430102/translations`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ translations: batch })
        });
        if (!response.ok) throw new Error('Network response was not ok');
        const data = await response.json();
        console.log('Translation batch fetched:', data.translations);
        return data.translations;
    } catch (error) {
        console.error('Failed to fetch translation batch:', error);
        return batch.reduce((acc, item) => {
            acc[item.text] = item.text; // Return original text in case of error
            return acc;
        }, {});
    }
}

// Process translation queue
async function processTranslationQueue() {
    if (translationQueue.length === 0) return;

    const batch = translationQueue.map(item => ({
        page_path: item.pagePath,
        language: item.language,
        text: item.text
    }));

    const results = await fetchTranslationBatch(batch);
    translationQueue.forEach((item, index) => {
        const translatedText = results[item.text] || item.text;
        const { pagePath, language, text } = item;

        translationDictionary[pagePath] ||= {};
        translationDictionary[pagePath][language] ||= {};
        translationDictionary[pagePath][language][text] = translatedText;
        item.resolve(translatedText);
    });
    translationQueue = [];
}

// Translator function with batching
async function translator(text, node) {
    const pagePath = getPagePath();
    const strippedText = text;

    // Wait for dictionary to be loaded if it's not already
    if (!dictionaryLoaded) {
        await dictionaryLoadingPromise;
    }

    // If current language is source language, return original text
    if (currentLanguage === sourceLanguage) {
        return strippedText;  // No translation needed
    }

    if (translationDictionary[pagePath] && translationDictionary[pagePath][currentLanguage] && translationDictionary[pagePath][currentLanguage][strippedText]) {
        return translationDictionary[pagePath][currentLanguage][strippedText];
    } else {
        return new Promise((resolve) => {
            translationQueue.push({ text: strippedText, pagePath, language: currentLanguage, resolve });
            if (!translationTimer) {
                translationTimer = setTimeout(async () => {
                    await processTranslationQueue();
                    translationTimer = null;
                }, 1500); // debounce period
            }
        });
    }
}

async function monitorCustomElements(pagePath, currentLanguage) {
    // Ensure translations are loaded
    await loadCustomElementTranslations(pagePath, currentLanguage);

    // Revert existing custom translations
    revertCustomElementTranslations();

    // Set up a periodic check
    applyCustomElementTranslations();
    customElementTranslationInterval = setInterval(() => {
        applyCustomElementTranslations();
    }, 700); // Check every second (adjust as necessary)
}

function applyCustomElementTranslations() {
    const pagePath = getPagePath();
    const translations = elementTranslations[pagePath]?.[currentLanguage] || [];

    translations.forEach(translation => {
        const { selector } = translation;
        const elements = document.querySelectorAll(selector);

        elements.forEach(element => {
            translateCustomElement(element, translation);
        });
    });
}

async function translateCustomElement(element, elementTranslation) {
    // Get or set the original HTML
    const originalHtml = element.getAttribute('data-original-html') || (() => {
        const html = element.cloneNode(true).outerHTML; // Clone without modifications
        element.setAttribute('data-original-html', html);
        return html;
    })();

    // Generate clean current HTML (excluding data-* attributes)
    const cleanOuterHtml = (() => {
        const clone = element.cloneNode(true);
        clone.removeAttribute('data-original-html');
        clone.removeAttribute('data-translated-html');
        return clone.outerHTML;
    })();

    // Generate clean translated HTML (excluding data-* attributes)
    const cleanTranslatedHtml = (() => {
        if (!element.hasAttribute('data-translated-html')) return null;
        const tempContainer = document.createElement('div');
        tempContainer.innerHTML = element.getAttribute('data-translated-html');
        const translatedClone = tempContainer.firstElementChild;
        translatedClone.removeAttribute('data-original-html');
        translatedClone.removeAttribute('data-translated-html');
        return translatedClone.outerHTML;
    })();

    if (cleanOuterHtml === cleanTranslatedHtml) return;
    if (cleanOuterHtml !== originalHtml) element.setAttribute('data-original-html', cleanOuterHtml);

    // Apply the translation
    switch (elementTranslation.action) {
        case 'replace':
            elementTranslation.target_attribute === 'text'
              ? (element.textContent = elementTranslation.replacement_value)
              : element.setAttribute(elementTranslation.target_attribute, elementTranslation.replacement_value);
            break;
        case 'append':
            elementTranslation.target_attribute === 'text'
              ? (element.textContent += elementTranslation.replacement_value)
              : element.setAttribute(
                elementTranslation.target_attribute,
                (element.getAttribute(elementTranslation.target_attribute) || '') + elementTranslation.replacement_value
              );
            break;
        case 'remove':
            elementTranslation.target_attribute
              ? element.removeAttribute(elementTranslation.target_attribute)
              : element.remove();
            break;
        default:
            console.warn(`Unknown translation action: ${elementTranslation.action}`);
    }

    // Save the clean translated state
    const updatedOuterHtml = (() => {
        const translatedClone = element.cloneNode(true);
        translatedClone.removeAttribute('data-original-html');
        translatedClone.removeAttribute('data-translated-html');
        return translatedClone.outerHTML;
    })();
    element.setAttribute('data-translated-html', updatedOuterHtml);
}

// Function to initialize the NodesTranslator
async function initializeTranslator() {
    const pagePath = getPagePath();
    // Ensure the dictionary is loaded only once
    if (!dictionaryLoadingPromise) {
        dictionaryLoadingPromise = loadTranslationDictionary(pagePath, currentLanguage).then(pageDictionary => {
            translationDictionary[pagePath] = translationDictionary[pagePath] || {};
            translationDictionary[pagePath][currentLanguage] = pageDictionary;
            dictionaryLoaded = true;
        });
    }
    await dictionaryLoadingPromise;

    // Run element translation
    await monitorCustomElements(pagePath, currentLanguage);

    // Update iframes with current language
    updateAllIframes();
    setupIframeObserver();

    // Initialize NodesTranslator with the translator function if not already initialized
    if (!domTranslator) {
        domTranslator = new window.NodesTranslator((text, node) => translator(text, node), { lazyTranslate: false, ignoredTags: ['style', 'script', 'custom-language-selector', 'language-selector'] });
        domTranslator.observe(document.documentElement);
    }
}

// Function to handle URL changes
async function handleUrlChange() {
    console.log('URL path changed. Reloading dictionary...');
    const pagePath = getPagePath();

    // Reset dictionary loading state
    dictionaryLoaded = false;
    dictionaryLoadingPromise = null;

    await initializeTranslator();
}

// Function to handle language change
async function handleLanguageChange(newLanguage) {
    if (newLanguage !== currentLanguage) {
        setCookie('language', newLanguage, 7);
        currentLanguage = newLanguage;
        console.log(`Language changed to: ${newLanguage}`);
        revertToOriginal();
        updateAllIframes();
        await handleUrlChange(); // Reload the dictionary for the new language
    }
}

// Listen for URL path changes
window.addEventListener('popstate', handleUrlChange);

// Monkey patch history.pushState and history.replaceState
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;

history.pushState = function() {
    originalPushState.apply(this, arguments);
    handleUrlChange();
};

history.replaceState = function() {
    originalReplaceState.apply(this, arguments);
    handleUrlChange();
};

// Function to get a URL parameter by name
function getUrlParameter(name) {
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.get(name);
}

// Function to remove a parameter from the URL without reloading the page
function removeUrlParameter(param) {
    const url = new URL(window.location.href);
    url.searchParams.delete(param);
}

// Fetch available languages and determine the current language
async function determineCurrentLanguage() {
    const availableLanguages = await fetchLanguages(); // Fetch available languages from the API
    const urlLanguage = getUrlParameter('language'); // Check if language is in URL

    if (urlLanguage) {
        const matchingLanguage = availableLanguages.find(lang => lang.code.toLowerCase() === urlLanguage.toLowerCase());
        if (matchingLanguage) {
            console.log(`Language selected from URL: ${matchingLanguage.code}`);
            removeUrlParameter('language'); // Remove language parameter from URL
            return matchingLanguage.code;
        } else {
            console.warn(`URL language (${urlLanguage}) not found in available languages. Using fallback.`);
        }
    }

    // Get the user language detection setting
    const userLanguageDetection = "browser_language";

    // Use the LanguageAutoSelector to determine the best language
    const languageAutoSelector = new LanguageAutoSelector('https://rubyroid.tech/', '8019172b-93c6-4dfa-ba1e-256425430102', '');
    const selectedLanguage = await languageAutoSelector.selectLanguage(availableLanguages, userLanguageDetection);

    return selectedLanguage;
}


// For initial load
window.addEventListener('load', async () => {
    await fetchSourceLanguage(); // Fetch the source language when the page loads
    currentLanguage = currentLanguage || sourceLanguage; // If no language is selected, use source language as default
    handleUrlChange(); // Continue with handling the URL change
});

// Listen for custom language change event
window.addEventListener('message', (event) => {
    if (event.data.type === 'languageChange') {
        const newLanguage = event.data.detail.language;
        handleLanguageChange(newLanguage);
    }
});

// Function to revert text to original
function revertToOriginal() {
    if (domTranslator) {
        domTranslator.unobserve(document.documentElement);
        domTranslator = null;
        console.log('Reverted to original text.');
    }
    cleanupIframeObserver();
}

function revertCustomElementTranslations() {
    // Disconnect the MutationObserver
    if (customElementTranslationInterval) {
        clearInterval(customElementTranslationInterval);
        customElementTranslationInterval = null;
    }

    // Revert elements to their original state
    const translatedElements = document.querySelectorAll('[data-original-html]');
    translatedElements.forEach(element => {
        const originalHtml = element.getAttribute('data-original-html');
        if (originalHtml) {
            const parent = element.parentNode;
            const tempContainer = document.createElement('div');
            tempContainer.innerHTML = originalHtml;

            if (parent && tempContainer.firstChild) {
                parent.replaceChild(tempContainer.firstChild, element);
            }
        }
    });
}

// Fetch source language dynamically
async function fetchLanguages() {
    try {
        const response = await fetch(`https://rubyroid.tech//weblang/websites/8019172b-93c6-4dfa-ba1e-256425430102/languages`);
        if (!response.ok) throw new Error('Failed to fetch languages');
        const languages = await response.json();
        return languages
    } catch (error) {
        console.error('Failed to fetch the source language:', error);
    }
}

// Load the LanguageAutoSelector script
const languageAutoSelectorScript = document.createElement('script');
languageAutoSelectorScript.src = 'https://rubyroid.tech//js/weblang/LanguageAutoSelector.js';
document.head.appendChild(languageAutoSelectorScript);

// Load the bundled script
const script = document.createElement('script');
script.src = 'https://rubyroid.tech//main-packed.js';
document.head.appendChild(script);

// Initialize and use NodesTranslator once the script is loaded
script.onload = async function() {
    const urlLanguage = getUrlParameter('language');
    if (window.NodesTranslator) {
        if (!sourceLanguage) {
            await fetchSourceLanguage();
            if (urlLanguage) {
                currentLanguage = await determineCurrentLanguage();
            } else {
                currentLanguage = currentLanguage || await determineCurrentLanguage();
            }
            setCookie('language', currentLanguage, 7); // Set the cookie for consistency
        }

        await initializeTranslator();
    } else {
        console.error('NodesTranslator is not defined.');
    }
    // Dynamically load LanguageController.js for UI management after initializing translation functionality
};

// Function to transform language code (EN-GB -> en)
function transformLanguageCode(languageCode) {
    if (!languageCode) return '';
    return languageCode.split('-')[0].toLowerCase();
}

// Function to update iframe src with new language
function updateIframeSrc(iframe) {
    const src = iframe.getAttribute('src');
    if (!src || !src.includes('instance=')) return;

    try {
        const url = new URL(src);
        const targetLang = transformLanguageCode(currentLanguage);
        const currentLang = url.searchParams.get('lang');

        // Skip update if language is already correct
        if (currentLang === targetLang) return;

        // Set the lang parameter
        url.searchParams.set('lang', targetLang);

        // Update isPrimaryLanguage if it exists and is true
        const isPrimary = url.searchParams.get('isPrimaryLanguage');
        if (isPrimary === 'true') {
            url.searchParams.set('isPrimaryLanguage', 'false');
        }

        iframe.setAttribute('src', url.toString());
        console.log(`Updated iframe src: ${url.toString()}`);
    } catch (error) {
        console.error('Error updating iframe src:', error);
    }
}

// Function to update all iframes on the page
function updateAllIframes() {
    const iframes = document.querySelectorAll('iframe[src*="instance="]');
    iframes.forEach(updateIframeSrc);
}

// Function to set up iframe observer for dynamically added iframes
function setupIframeObserver() {
    if (iframeObserver) { iframeObserver.disconnect() }

    iframeObserver = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            mutation.addedNodes.forEach((node) => {
                if (node.nodeType !== Node.ELEMENT_NODE) return;

                // Check if the added node is an iframe
                if (node.tagName === 'IFRAME' && node.src && node.src.includes('instance=')) { updateIframeSrc(node) }
                const iframes = node.querySelectorAll?.('iframe[src*="instance="]') || [];
                iframes.forEach(updateIframeSrc);
            });
        });
    });

    iframeObserver.observe(document.body, {
        childList: true,
        subtree: true
    });
}

// Function to cleanup iframe observer
function cleanupIframeObserver() {
    if (!iframeObserver) return;

    iframeObserver.disconnect();
    iframeObserver = null;
}
