// app/modules/dev_tools/static/admin/js/translation-editor.js

const transLog = window.LogConfig.createLogger('TRANSLATION_EDITOR');

/**
 * Translation Editor Alpine.js Component
 * Browse, search, and edit UI string translations across all modules.
 */
function translationEditor() {
    return {
        // Inherit base layout functionality
        ...data(),

        // Page identifier (for sidebar menu highlight)
        currentPage: 'translation-editor',

        // Data
        modules: [],
        keys: [],
        languages: [],
        stats: {},

        // Filters
        selectedModule: 'all',
        searchQuery: '',
        filterMode: 'all',  // 'all' | 'missing' | 'has_variables'

        // Editing
        editingCell: null,  // {module, path, language}
        editValue: '',
        saving: false,

        // Pagination (uses pagination macro contract)
        pagination: { page: 1, total: 0, per_page: 50 },

        // UI
        loading: true,
        error: null,

        // Computed-like getters
        get filteredKeys() {
            let result = this.keys;

            // Module filter
            if (this.selectedModule !== 'all') {
                result = result.filter(k => k.module === this.selectedModule);
            }

            // Filter mode
            if (this.filterMode === 'missing') {
                result = result.filter(k =>
                    this.languages.some(lang => k.values[lang] === null)
                );
            } else if (this.filterMode === 'has_variables') {
                result = result.filter(k => k.has_variables);
            }

            // Search
            if (this.searchQuery.trim()) {
                const q = this.searchQuery.toLowerCase();
                result = result.filter(k => {
                    if (k.path.toLowerCase().includes(q)) return true;
                    if (k.module.toLowerCase().includes(q)) return true;
                    return this.languages.some(lang => {
                        const val = k.values[lang];
                        return val && val.toLowerCase().includes(q);
                    });
                });
            }

            // Update pagination total
            this.pagination.total = result.length;

            return result;
        },

        get totalPages() {
            return Math.max(1, Math.ceil(this.pagination.total / this.pagination.per_page));
        },

        get startIndex() {
            if (this.pagination.total === 0) return 0;
            return ((this.pagination.page - 1) * this.pagination.per_page) + 1;
        },

        get endIndex() {
            return Math.min(this.pagination.page * this.pagination.per_page, this.pagination.total);
        },

        get pageNumbers() {
            const total = this.totalPages;
            const current = this.pagination.page;
            const maxVisible = 5;

            if (total <= maxVisible) {
                return Array.from({length: total}, (_, i) => i + 1);
            }

            const half = Math.floor(maxVisible / 2);
            let start = Math.max(1, current - half);
            let end = Math.min(total, start + maxVisible - 1);

            if (end - start < maxVisible - 1) {
                start = Math.max(1, end - maxVisible + 1);
            }

            const pages = [];
            if (start > 1) pages.push(1);
            if (start > 2) pages.push('...');
            for (let i = start; i <= end; i++) pages.push(i);
            if (end < total - 1) pages.push('...');
            if (end < total) pages.push(total);

            return pages;
        },

        get paginatedKeys() {
            const start = (this.pagination.page - 1) * this.pagination.per_page;
            return this.filteredKeys.slice(start, start + this.pagination.per_page);
        },

        previousPage() {
            if (this.pagination.page > 1) this.pagination.page--;
        },

        nextPage() {
            if (this.pagination.page < this.totalPages) this.pagination.page++;
        },

        goToPage(p) {
            if (typeof p === 'number') this.pagination.page = p;
        },

        async init() {
            if (window._translationEditorInitialized) return;
            window._translationEditorInitialized = true;

            this.$nextTick(() => {
                if (typeof this.initBase === 'function') this.initBase();
            });

            if (window.PlatformSettings) {
                this.pagination.per_page = await window.PlatformSettings.getRowsPerPage();
            }

            await this.loadKeys();
        },

        async loadKeys() {
            this.loading = true;
            this.error = null;

            try {
                const resp = await apiClient.get('/admin/translations/keys');
                this.modules = resp.modules;
                this.keys = resp.keys;
                this.languages = resp.languages;
                this.stats = resp.stats;
                this.pagination.total = resp.keys.length;
            } catch (e) {
                this.error = e.message;
                transLog.error('Failed to load translations:', e);
            } finally {
                this.loading = false;
            }
        },

        isEditing(entry, lang) {
            return this.editingCell &&
                this.editingCell.module === entry.module &&
                this.editingCell.path === entry.path &&
                this.editingCell.language === lang;
        },

        startEdit(entry, lang) {
            // Save any current edit first
            if (this.editingCell) {
                this._doSave();
            }

            this.editingCell = {
                module: entry.module,
                path: entry.path,
                language: lang,
            };
            this.editValue = entry.values[lang] || '';

            // Focus the textarea
            this.$nextTick(() => {
                const ta = this.$el.querySelector('textarea[x-ref="editInput"]');
                if (ta) ta.focus();
            });
        },

        cancelEdit() {
            this.editingCell = null;
            this.editValue = '';
        },

        async saveEdit() {
            try {
                await this._doSave();
            } catch (err) {
                transLog.error('Failed to save edit:', err);
            }
        },

        async saveAndNext(entry, lang) {
            await this._doSave();  // noqa: JS-006 — error handling in _doSave

            // Move to next language column, or next row
            const langIdx = this.languages.indexOf(lang);
            if (langIdx < this.languages.length - 1) {
                this.startEdit(entry, this.languages[langIdx + 1]);
            } else {
                // Move to next row, first language
                const entries = this.paginatedKeys;
                const rowIdx = entries.findIndex(
                    e => e.module === entry.module && e.path === entry.path
                );
                if (rowIdx < entries.length - 1) {
                    this.startEdit(entries[rowIdx + 1], this.languages[0]);
                }
            }
        },

        async _doSave() {
            if (!this.editingCell) return;

            const { module, path, language } = this.editingCell;

            // Find the current entry
            const entry = this.keys.find(
                k => k.module === module && k.path === path
            );
            if (!entry) {
                this.editingCell = null;
                return;
            }

            const oldValue = entry.values[language];
            const newValue = this.editValue;

            // Skip if unchanged
            if ((oldValue || '') === newValue) {
                this.editingCell = null;
                this.editValue = '';
                return;
            }

            this.saving = true;
            this.editingCell = null;

            try {
                const updated = await apiClient.put('/admin/translations/key', {
                    module,
                    path,
                    language,
                    value: newValue,
                });

                // Update the local entry
                entry.values = updated.values;
                entry.has_variables = updated.has_variables;
                if (updated.variables) {
                    entry.variables = updated.variables;
                }

                // Recalculate missing stats
                this._recalcStats();
            } catch (e) {
                this.error = e.message;
                transLog.error('Failed to save translation:', e);
            } finally {
                this.saving = false;
                this.editValue = '';
            }
        },

        _recalcStats() {
            const missing = {};
            for (const lang of this.languages) {
                missing[lang] = this.keys.filter(k => k.values[lang] === null).length;
            }
            this.stats = {
                ...this.stats,
                missing,
            };
        },

        getMissingVars(entry, value) {
            if (!entry.variables || !value) return [];
            return entry.variables.filter(v => !value.includes(`{${v}}`));
        },
    };
}
