/**
 * JavaScript i18n Support
 *
 * Loads translations from module locale files for use in JavaScript.
 * Provides the same translation interface as the Python/Jinja2 system.
 *
 * Usage:
 *   // Initialize with language and modules to preload
 *   await I18n.init('en', ['catalog', 'orders']);
 *
 *   // Or load modules later
 *   await I18n.loadModule('inventory');
 *
 *   // Translate (in JS)
 *   const message = I18n.t('catalog.messages.product_created');
 *   const withVars = I18n.t('common.welcome', { name: 'John' });
 *
 *   // Translate (in Alpine templates — reactive, updates when translations load)
 *   // <span x-text="$t('catalog.messages.product_created')"></span>
 *   // <span x-text="$t('common.welcome', {name: user})"></span>
 */

// Create logger for i18n module (with silent fallback if LogConfig not yet loaded)
const i18nLog = window.LogConfig ? window.LogConfig.createLogger('I18N') : {
    warn: () => {},   // Silent fallback - i18n loads early before LogConfig
    error: () => {},
    info: () => {},
    debug: () => {}
};

const I18n = {
    _translations: {},
    _language: 'en',
    _loaded: new Set(),
    _loading: new Map(),  // Track in-progress loads

    /**
     * Initialize with language (call once on page load)
     * @param {string} language - Language code (en, fr, de, lb)
     * @param {string[]} modules - Optional array of modules to preload
     */
    async init(language = 'en', modules = []) {
        this._language = language;
        // Load shared translations first
        await this.loadShared();
        // Preload any specified modules
        if (modules && modules.length > 0) {
            await Promise.all(modules.map(m => this.loadModule(m)));
        }
        this._notifyReady();
    },

    /**
     * Load shared/common translations from static/locales
     */
    async loadShared() {
        if (this._loaded.has('shared')) return;

        try {
            const response = await fetch(`/static/locales/${this._language}.json`);
            if (response.ok) {
                const data = await response.json();
                this._translations = { ...this._translations, ...data };
                this._loaded.add('shared');
            }
        } catch (e) {
            i18nLog.warn('Failed to load shared translations:', e);
        }
    },

    /**
     * Load module-specific translations
     * @param {string} module - Module name (e.g., 'catalog', 'orders')
     */
    async loadModule(module) {
        if (this._loaded.has(module)) return;

        try {
            const response = await fetch(`/static/modules/${module}/locales/${this._language}.json`);
            if (response.ok) {
                const data = await response.json();
                // Namespace under module code (matching Python i18n behavior)
                this._translations[module] = data;
                this._loaded.add(module);
            }
        } catch (e) {
            i18nLog.warn(`Failed to load ${module} translations:`, e);
        }
    },

    /**
     * Get translation by key path
     * @param {string} key - Dot-notation key (e.g., 'catalog.messages.product_created')
     * @param {object} vars - Variables for interpolation
     * @returns {string} Translated string or key if not found
     */
    t(key, vars = {}) {
        const keys = key.split('.');
        let value = this._translations;

        for (const k of keys) {
            if (value && typeof value === 'object' && k in value) {
                value = value[k];
            } else {
                i18nLog.warn(`Missing translation: ${key}`);
                return key;
            }
        }

        if (typeof value !== 'string') return key;

        // Interpolate variables: {name} -> value
        return value.replace(/\{(\w+)\}/g, (match, name) => {
            return vars[name] !== undefined ? vars[name] : match;
        });
    },

    /**
     * Check if a translation key exists
     * @param {string} key - Dot-notation key
     * @returns {boolean} True if key exists
     */
    has(key) {
        const keys = key.split('.');
        let value = this._translations;

        for (const k of keys) {
            if (value && typeof value === 'object' && k in value) {
                value = value[k];
            } else {
                return false;
            }
        }

        return typeof value === 'string';
    },

    /**
     * Get current language
     * @returns {string} Current language code
     */
    getLanguage() {
        return this._language;
    },

    /**
     * Change language (reloads all loaded modules)
     * @param {string} language - New language code
     */
    async setLanguage(language) {
        if (language === this._language) return;

        try {
            const loadedModules = [...this._loaded];
            this._language = language;
            this._translations = {};
            this._loaded.clear();

            // Reload all previously loaded modules
            for (const module of loadedModules) {
                if (module === 'shared') {
                    await this.loadShared();
                } else {
                    await this.loadModule(module);
                }
            }
            this._notifyReady();
        } catch (e) {
            i18nLog.error('Failed to change language:', e);
        }
    },

    /**
     * Notify Alpine (and other listeners) that translations are ready.
     * Bumps the Alpine store version so reactive $t() bindings re-evaluate.
     */
    _notifyReady() {
        this._ready = true;
        // Bump Alpine store version if available (triggers $t() re-evaluation)
        if (typeof Alpine !== 'undefined' && Alpine.store) {
            const store = Alpine.store('i18n');
            if (store) store._v++;
        }
        document.dispatchEvent(new CustomEvent('i18n:ready'));
    }
};

// Register Alpine magic $t() — reactive wrapper around I18n.t()
// Works across all frontends (merchant, admin, store, storefront)
document.addEventListener('alpine:init', () => {
    // Store with a reactive version counter
    Alpine.store('i18n', { _v: 0 });

    // $t('key', {vars}) — use in x-text, x-html, or any Alpine expression
    // Before translations load, returns the key (which matches fallback text);
    // after _notifyReady() bumps _v, Alpine re-evaluates with loaded translations.
    Alpine.magic('t', (el) => {
        return (key, vars) => {
            void Alpine.store('i18n')._v;  // reactive dependency
            return I18n.t(key, vars);
        };
    });
});

// Export for module usage
if (typeof window !== 'undefined') {
    window.I18n = I18n;
}
