// launcher.js - Funcionalidad del Launcher GUI

class LauncherManager {
    constructor() {
        this.currentGroup = null;
        this.groups = [];
        this.scripts = [];
        this.favorites = new Set();
        this.history = [];
        this.categories = {};
        this.currentFilter = 'all';
        this.currentEditingGroup = null;
        this.pythonEnvs = [];
        this.markdownFiles = [];
    }

    async init() {
        console.log('Inicializando Launcher GUI...');
        await this.loadCategories();
        await this.loadPythonEnvironments();
        await this.loadGroups();
        await this.loadFavorites();
        await this.loadHistory();
        this.setupEventListeners();
        this.renderInterface();
    }

    async loadCategories() {
        try {
            const response = await fetch('/api/launcher-categories');
            this.categories = await response.json();
        } catch (error) {
            console.error('Error loading launcher categories:', error);
        }
    }

    async loadPythonEnvironments() {
        try {
            const response = await fetch('/api/python-environments');
            this.pythonEnvs = await response.json();
            this.renderPythonEnvSelector();
        } catch (error) {
            console.error('Error loading Python environments:', error);
        }
    }

    renderPythonEnvSelector() {
        const selector = document.getElementById('group-python-env');
        if (!selector) return;

        selector.innerHTML = '';
        this.pythonEnvs.forEach(env => {
            const option = document.createElement('option');
            option.value = env.name;
            option.textContent = env.display_name;
            selector.appendChild(option);
        });
    }

    async loadGroups() {
        try {
            const response = await fetch('/api/launcher-groups');
            this.groups = await response.json();
            this.renderGroupSelector();
        } catch (error) {
            console.error('Error loading launcher groups:', error);
        }
    }

    async loadFavorites() {
        try {
            const response = await fetch('/api/launcher-favorites');
            const data = await response.json();
            this.favorites = new Set(data.favorites.map(f => `${f.group_id}_${f.script_name}`));
            await this.renderFavorites(data.favorites);
        } catch (error) {
            console.error('Error loading favorites:', error);
        }
    }

    async loadHistory() {
        try {
            const response = await fetch('/api/launcher-history');
            const data = await response.json();
            this.history = data.history || [];
            this.renderHistory();
        } catch (error) {
            console.error('Error loading history:', error);
        }
    }

    setupEventListeners() {
        // Event listener para el formulario de grupos
        const groupForm = document.getElementById('group-form');
        if (groupForm) {
            groupForm.addEventListener('submit', (e) => {
                e.preventDefault();
                this.saveGroup();
            });
        }

        // Event listener para el formulario de metadatos de scripts
        const scriptMetadataForm = document.getElementById('script-metadata-form');
        if (scriptMetadataForm) {
            scriptMetadataForm.addEventListener('submit', (e) => {
                e.preventDefault();
                this.saveScriptMetadata();
            });
        }
    }

    renderInterface() {
        this.renderGroupSelector();
        this.renderCategoryFilter();
        this.updateFavoritesCount();
    }

    renderGroupSelector() {
        const selector = document.getElementById('launcher-group-select');
        if (!selector) return;

        // Guardar la selección actual
        const currentSelection = this.getCurrentGroupSelection();

        selector.innerHTML = '<option value="">-- Seleccionar Grupo --</option>';

        // Ordenar grupos alfabéticamente por nombre
        const sortedGroups = [...this.groups].sort((a, b) => a.name.localeCompare(b.name));

        sortedGroups.forEach(group => {
            const option = document.createElement('option');
            option.value = group.id;
            option.textContent = group.name;
            option.dataset.category = group.category;
            option.dataset.description = group.description;
            selector.appendChild(option);
        });

        // Restaurar la selección guardada
        this.restoreGroupSelection(currentSelection);
    }

    // Nuevo método para obtener la selección actual del localStorage
    getCurrentGroupSelection() {
        const currentValue = document.getElementById('launcher-group-select')?.value;
        return localStorage.getItem('launcher-selected-group') || currentValue || '';
    }

    // Nuevo método para restaurar la selección desde localStorage
    restoreGroupSelection(groupId) {
        const selector = document.getElementById('launcher-group-select');
        if (!selector || !groupId) return;

        // Verificar que el grupo aún existe
        const groupExists = this.groups.some(g => g.id === groupId);
        if (groupExists) {
            selector.value = groupId;
            // Cargar scripts del grupo restaurado automáticamente
            this.loadLauncherScripts();
        } else {
            // Si el grupo ya no existe, limpiar localStorage
            localStorage.removeItem('launcher-selected-group');
        }
    }

    renderCategoryFilter() {
        const filterContainer = document.querySelector('.category-filter .flex');
        if (!filterContainer) return;

        // Limpiar botones existentes excepto "Todas"
        const buttons = filterContainer.querySelectorAll('.category-btn:not([data-category="all"])');
        buttons.forEach(btn => btn.remove());

        // Agregar botones por categoría
        Object.keys(this.categories).forEach(category => {
            const categoryData = this.categories[category];
            const button = document.createElement('button');
            button.className = 'category-btn px-3 py-1 rounded-full text-sm border';
            button.dataset.category = category;
            button.innerHTML = `${categoryData.icon} ${category}`;
            button.onclick = () => this.filterByCategory(category);
            filterContainer.appendChild(button);
        });
    }

    async loadLauncherScripts() {
        const groupId = document.getElementById('launcher-group-select').value;

        // Guardar la selección en localStorage
        if (groupId) {
            localStorage.setItem('launcher-selected-group', groupId);
        } else {
            localStorage.removeItem('launcher-selected-group');
        }

        if (!groupId) {
            this.scripts = [];
            this.markdownFiles = [];
            this.renderScripts();
            this.renderMarkdownFiles();
            this.updateManageScriptsButton(false);
            this.updateEditorButtons(false);
            return;
        }

        // Cargar scripts (parte crítica)
        try {
            const response = await fetch(`/api/launcher-scripts/${groupId}`);
            if (response.ok) {
                this.scripts = await response.json();
            } else {
                console.error('Error loading scripts:', response.status, response.statusText);
                this.scripts = [];
            }
        } catch (error) {
            console.error('Error loading launcher scripts:', error);
            this.scripts = [];
        }

        // Cargar archivos markdown (parte opcional)
        try {
            const markdownResponse = await fetch(`/api/launcher-markdown/${groupId}`);
            if (markdownResponse.ok) {
                const markdownData = await markdownResponse.json();
                this.markdownFiles = markdownData.files || [];
            } else {
                console.warn('No markdown files available for group:', groupId);
                this.markdownFiles = [];
            }
        } catch (error) {
            console.warn('Error loading markdown files (non-critical):', error);
            this.markdownFiles = [];
        }

        // Actualizar interfaz
        this.currentGroup = this.groups.find(g => g.id === groupId);
        this.updateGroupIcon();
        this.renderScripts();
        this.renderMarkdownFiles();
        this.updateManageScriptsButton(this.scripts.length > 0);
        this.updateEditorButtons(true); // Usar la nueva función
    }

    updateManageScriptsButton(show) {
        const button = document.getElementById('manage-scripts-btn');
        if (button) {
            button.style.display = show ? 'block' : 'none';
        }
    }

    // Función actualizada para mostrar/ocultar todos los botones
    updateEditorButtons(show) {
        const vscodeButton = document.getElementById('vscode-launcher-btn');
        const cursorButton = document.getElementById('cursor-launcher-btn');
        const folderButton = document.getElementById('folder-launcher-btn');
        const copyPathButton = document.getElementById('copy-path-launcher-btn');

        if (vscodeButton) {
            vscodeButton.style.display = show ? 'block' : 'none';
        }
        if (cursorButton) {
            cursorButton.style.display = show ? 'block' : 'none';
        }
        if (folderButton) {
            folderButton.style.display = show ? 'block' : 'none';
        }
        if (copyPathButton) {
            copyPathButton.style.display = show ? 'block' : 'none';
        }
    }

    updateGroupIcon() {
        const iconElement = document.getElementById('selected-group-icon');
        if (!iconElement || !this.currentGroup) return;

        // Intentar cargar icono personalizado
        const img = document.createElement('img');
        img.src = `/api/group-icon/launcher/${this.currentGroup.id}`;
        img.className = 'w-6 h-6 rounded';
        img.onerror = () => {
            // Fallback a icono por defecto
            iconElement.innerHTML = this.getDefaultIconForCategory(this.currentGroup.category);
        };
        img.onload = () => {
            iconElement.innerHTML = '';
            iconElement.appendChild(img);
        };
    }

    getDefaultIconForCategory(category) {
        const icons = {
            'Herramientas': '🔧',
            'Análisis': '📊',
            'Utilidades': '⚙️',
            'Desarrollo': '💻',
            'Visualización': '📈',
            'Otros': '📁'
        };
        return icons[category] || '📁';
    }

    renderScripts() {
        const grid = document.getElementById('launcher-scripts-grid');
        if (!grid) return;

        if (this.scripts.length === 0) {
            grid.innerHTML = `
                <div class="col-span-full empty-state">
                    <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
                    </svg>
                    <p class="text-lg font-medium">No hay scripts disponibles</p>
                    <p class="text-sm">Selecciona un grupo o verifica que el directorio contenga archivos .py</p>
                </div>
            `;
            return;
        }

        let filteredScripts = this.scripts;
        if (this.currentFilter !== 'all' && this.currentGroup) {
            // Filtrar solo si la categoría del grupo no coincide con el filtro
            const groupCategory = this.currentGroup.category;
            if (groupCategory !== this.currentFilter) {
                filteredScripts = [];
            }
        }

        grid.innerHTML = '';
        filteredScripts.forEach(script => {
            const favoriteId = `${this.currentGroup.id}_${script.name}`;
            const isFavorite = this.favorites.has(favoriteId);

            const card = document.createElement('div');
            card.className = `script-card ${isFavorite ? 'favorited' : ''}`;
            card.innerHTML = `
                <div class="flex justify-between items-start mb-2">
                    <h4 class="font-medium text-gray-900">${script.display_name}</h4>
                    <button class="favorite-star ${isFavorite ? 'active' : ''}"
                            onclick="launcherManager.toggleFavorite('${this.currentGroup.id}', '${script.name.replace(/'/g, "\\'")}')">
                        ⭐
                    </button>
                </div>
                <p class="text-sm text-gray-600 mb-3 line-clamp-2">${script.description || 'Script: ' + script.name}</p>
                <div class="flex justify-between items-center">
                    <span class="category-badge">${this.currentGroup.category}</span>
                    <div class="flex flex-col gap-1 text-xs">
                        <div class="flex gap-1">
                            ${script.long_description && script.long_description.trim() ? `
                            <button class="text-green-600 hover:underline"
                                    onclick="launcherManager.showDescriptionModal('${script.name.replace(/'/g, "\\'")}', '${this.escapeHtml(script.display_name)}')">
                                Descripción
                            </button>` : ''}
                            <button class="text-blue-500 hover:underline"
                                    onclick="launcherManager.showArgsModal('${script.name.replace(/'/g, "\\'")}', '${this.escapeHtml(script.display_name)}')">
                                Con Argumentos
                            </button>
                        </div>
                        <div class="flex gap-1">
                            <button class="bg-blue-500 text-white px-2 py-1 rounded hover:bg-blue-600 text-xs"
                                    onclick="launcherManager.executeScript('${script.name.replace(/'/g, "\\'")}', [], null, false)"
                                    title="Ejecutar con python.exe (muestra logs)">
                                🖥️ Con Log
                            </button>
                            <button class="bg-green-500 text-white px-2 py-1 rounded hover:bg-green-600 text-xs"
                                    onclick="launcherManager.executeScript('${script.name.replace(/'/g, "\\'")}', [], null, true)"
                                    title="Ejecutar con pythonw.exe (sin ventana de consola)">
                                🚀 Sin Log
                            </button>
                        </div>
                    </div>
                </div>
            `;
            grid.appendChild(card);
        });
    }

    renderMarkdownFiles() {
        const container = document.getElementById('markdown-files-section');
        if (!container) return;

        if (!this.currentGroup || this.markdownFiles.length === 0) {
            container.style.display = 'none';
            return;
        }

        container.style.display = 'block';
        const grid = document.getElementById('markdown-files-grid');
        if (!grid) return;

        grid.innerHTML = '';
        this.markdownFiles.forEach(file => {
            const card = document.createElement('div');
            card.className = 'markdown-file-card bg-white border rounded-lg p-3 hover:shadow-md transition-shadow cursor-pointer';
            card.innerHTML = `
                <div class="flex items-start justify-between">
                    <div class="flex-1">
                        <h4 class="font-medium text-gray-900 text-sm">${file.display_name}</h4>
                        <p class="text-xs text-gray-500 mt-1">
                            📄 ${(file.size / 1024).toFixed(1)} KB
                            ${file.level === 1 ? ' • Subdirectorio' : ''}
                        </p>
                    </div>
                    <span class="text-xs text-gray-400">${this.getTimeAgo(file.modified)}</span>
                </div>
            `;
            card.onclick = () => this.openMarkdownViewer(file.relative_path, file.display_name);
            grid.appendChild(card);
        });
    }

    async openMarkdownViewer(relativePath, displayName) {
        if (!this.currentGroup) return;

        try {
            const response = await fetch(`/api/launcher-markdown-content/${this.currentGroup.id}/${encodeURIComponent(relativePath)}`);
            const result = await response.json();

            if (result.status === 'success') {
                const modal = document.getElementById('markdown-viewer-modal');
                const titleElement = document.getElementById('markdown-viewer-title');
                const pathElement = document.getElementById('markdown-viewer-path');
                const contentElement = document.getElementById('markdown-viewer-content');

                if (modal && titleElement && contentElement) {
                    titleElement.textContent = displayName;
                    pathElement.textContent = `Archivo: ${relativePath}`;

                    // Renderizar markdown
                    const md = window.markdownit();
                    contentElement.innerHTML = md.render(result.content);

                    modal.classList.remove('hidden');
                }
            } else {
                alert(`Error: ${result.message}`);
            }
        } catch (error) {
            console.error('Error loading markdown file:', error);
            alert('Error cargando archivo Markdown');
        }
    }

    escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    async showDescriptionModal(scriptName, displayName) {
        if (!this.currentGroup) return;

        try {
            // Cargar metadatos del script para obtener la descripción larga
            const response = await fetch(`/api/launcher-script-metadata/${this.currentGroup.id}/${scriptName}`);
            const metadata = await response.json();

            const modal = document.getElementById('script-description-modal');
            const scriptNameElement = document.getElementById('desc-modal-script-name');
            const scriptFileElement = document.getElementById('desc-modal-script-file');
            const contentElement = document.getElementById('script-description-content');

            if (modal && scriptNameElement && contentElement) {
                scriptNameElement.textContent = displayName;
                scriptFileElement.textContent = `Archivo: ${scriptName}`;

                // Renderizar markdown
                if (metadata.long_description && metadata.long_description.trim()) {
                    const md = window.markdownit();
                    contentElement.innerHTML = md.render(metadata.long_description);
                } else {
                    contentElement.innerHTML = '<p class="text-gray-500 italic">No hay descripción disponible para este script.</p>';
                }

                modal.classList.remove('hidden');
            }
        } catch (error) {
            console.error('Error loading script description:', error);
            alert('Error cargando la descripción del script');
        }
    }

    // === GESTIÓN DE SCRIPTS INDIVIDUALES ===

    async openScriptManager() {
        if (!this.currentGroup) {
            alert('Selecciona un grupo primero');
            return;
        }

        const modal = document.getElementById('script-manager-modal');
        const groupInfo = document.getElementById('script-manager-group-info');

        if (modal && groupInfo) {
            groupInfo.textContent = `Grupo: ${this.currentGroup.name} (${this.currentGroup.category})`;
            await this.loadAllScriptsForManagement();
            modal.classList.remove('hidden');
        }
    }

    closeScriptManager() {
        const modal = document.getElementById('script-manager-modal');
        if (modal) {
            modal.classList.add('hidden');
        }
    }

    async loadAllScriptsForManagement() {
        if (!this.currentGroup) return;

        try {
            const response = await fetch(`/api/launcher-scripts-all/${this.currentGroup.id}`);
            const allScripts = await response.json();
            this.renderScriptManagerList(allScripts);
        } catch (error) {
            console.error('Error loading all scripts for management:', error);
        }
    }

    renderScriptManagerList(scripts) {
        const list = document.getElementById('script-manager-list');
        if (!list) return;

        if (scripts.length === 0) {
            list.innerHTML = `
                <div class="text-center text-gray-500 py-8">
                    <p>No hay scripts Python en este directorio</p>
                </div>
            `;
            return;
        }

        list.innerHTML = '';
        scripts.forEach(script => {
            const item = document.createElement('div');
            item.className = `border rounded-lg p-4 ${script.hidden ? 'bg-gray-50 border-gray-300' : 'bg-white border-gray-200'}`;
            item.innerHTML = `
                <div class="flex justify-between items-start">
                    <div class="flex-1">
                        <div class="flex items-center gap-2 mb-1">
                            <h4 class="font-medium ${script.hidden ? 'text-gray-500' : 'text-gray-900'}">${script.display_name}</h4>
                            ${script.hidden ? '<span class="text-xs bg-gray-200 text-gray-600 px-2 py-1 rounded">Oculto</span>' : ''}
                        </div>
                        <p class="text-sm text-gray-600 mb-2">${script.description || 'Sin descripción'}</p>
                        <p class="text-xs text-gray-500">Archivo: ${script.name}</p>
                    </div>
                    <div class="flex gap-2">
                        <button onclick="launcherManager.editScriptMetadata('${script.name.replace(/'/g, "\\'")}')"
                                class="text-blue-500 hover:underline text-sm">
                            Editar
                        </button>
                    </div>
                </div>
            `;
            list.appendChild(item);
        });
    }

    async editScriptMetadata(scriptName) {
        if (!this.currentGroup) return;

        try {
            const response = await fetch(`/api/launcher-script-metadata/${this.currentGroup.id}/${scriptName}`);
            const metadata = await response.json();

            // Poblar el formulario
            document.getElementById('edit-meta-group-id').value = this.currentGroup.id;
            document.getElementById('edit-meta-script-name').value = scriptName;
            document.getElementById('edit-meta-filename-display').textContent = scriptName;
            document.getElementById('edit-meta-display-name').value = metadata.display_name || scriptName.replace('.py', '');
            document.getElementById('edit-meta-description').value = metadata.description || '';
            document.getElementById('edit-meta-long-description').value = metadata.long_description || '';
            document.getElementById('edit-meta-hidden').checked = metadata.hidden || false;

            // Mostrar modal
            document.getElementById('script-metadata-editor-modal').classList.remove('hidden');
        } catch (error) {
            console.error('Error loading script metadata:', error);
            alert('Error cargando metadatos del script');
        }
    }

    closeScriptMetadataEditor() {
        document.getElementById('script-metadata-editor-modal').classList.add('hidden');
    }

    async saveScriptMetadata() {
        const groupId = document.getElementById('edit-meta-group-id').value;
        const scriptName = document.getElementById('edit-meta-script-name').value;
        const metadata = {
            display_name: document.getElementById('edit-meta-display-name').value,
            description: document.getElementById('edit-meta-description').value,
            long_description: document.getElementById('edit-meta-long-description').value,
            hidden: document.getElementById('edit-meta-hidden').checked
        };

        try {
            const response = await fetch(`/api/launcher-script-metadata/${groupId}/${scriptName}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(metadata)
            });

            const result = await response.json();
            if (result.status === 'success') {
                this.closeScriptMetadataEditor();
                // Recargar datos
                await this.loadAllScriptsForManagement();
                await this.loadLauncherScripts(); // Actualizar la vista principal también
            } else {
                alert(`Error: ${result.message}`);
            }
        } catch (error) {
            console.error('Error saving script metadata:', error);
            alert('Error guardando metadatos del script');
        }
    }

    // === GESTIÓN DE GRUPOS (actualizada) ===

    populateGroupForm(group) {
        document.getElementById('group-name').value = group.name;
        document.getElementById('group-description').value = group.description || '';
        document.getElementById('group-category').value = group.category;
        document.getElementById('group-version').value = group.version || '1.0';
        document.getElementById('group-python-env').value = group.python_env || 'base';
        document.getElementById('group-directory').value = group.directory;
    }

    clearGroupForm() {
        document.getElementById('group-name').value = '';
        document.getElementById('group-description').value = '';
        document.getElementById('group-category').value = 'Otros';
        document.getElementById('group-version').value = '1.0';
        document.getElementById('group-python-env').value = 'base';
        document.getElementById('group-directory').value = '';
        document.getElementById('delete-group-btn').style.display = 'none';
    }

    async saveGroup() {
        const formData = {
            name: document.getElementById('group-name').value,
            description: document.getElementById('group-description').value,
            category: document.getElementById('group-category').value,
            version: document.getElementById('group-version').value,
            python_env: document.getElementById('group-python-env').value,
            directory: document.getElementById('group-directory').value
        };

        try {
            let response;
            if (this.currentEditingGroup) {
                // Actualizar grupo existente
                response = await fetch(`/api/launcher-groups/${this.currentEditingGroup.id}`, {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(formData)
                });
            } else {
                // Crear nuevo grupo
                response = await fetch('/api/launcher-groups', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(formData)
                });
            }

            const result = await response.json();
            if (result.status === 'success') {
                await this.loadGroups();
                this.closeGroupEditor();
                this.renderInterface();
            } else {
                alert(`Error: ${result.message}`);
            }
        } catch (error) {
            console.error('Error saving group:', error);
            alert('Error al guardar el grupo');
        }
    }

    renderExistingGroups() {
        const container = document.getElementById('existing-groups-list');
        if (!container) return;

        container.innerHTML = '';
        this.groups.forEach(group => {
            const envInfo = this.pythonEnvs.find(env => env.name === group.python_env);
            const envDisplay = envInfo ? envInfo.display_name : group.python_env;

            const item = document.createElement('div');
            item.className = 'group-list-item';
            item.innerHTML = `
                <div class="group-icon-small default">
                    ${this.getDefaultIconForCategory(group.category)}
                </div>
                <div class="group-info">
                    <div class="group-name">${group.name}</div>
                    <div class="group-category">${group.category} • ${envDisplay}</div>
                </div>
                <button class="text-blue-500 hover:underline text-sm" onclick="launcherManager.editGroup('${group.id}')">
                    Editar
                </button>
            `;
            container.appendChild(item);
        });
    }

    renderHistory() {
        const historyList = document.getElementById('history-list');
        if (!historyList) return;

        if (this.history.length === 0) {
            historyList.innerHTML = `
                <div class="text-center text-gray-500 py-4">
                    <p>No hay ejecuciones recientes</p>
                </div>
            `;
            return;
        }

        historyList.innerHTML = '';
        this.history.slice(0, 10).forEach(entry => {
            const group = this.groups.find(g => g.id === entry.group_id);
            const groupName = group ? group.name : 'Grupo desconocido';

            const timeAgo = this.getTimeAgo(entry.executed_date);
            const statusClass = entry.status === 'success' ? 'success' :
                entry.status === 'error' ? 'error' : 'running';

            // Iconos y mensajes más descriptivos por status
            let statusIcon, statusText;
            switch (entry.status) {
                case 'success':
                    statusIcon = '✅';
                    statusText = 'Completado';
                    break;
                case 'error':
                    statusIcon = '❌';
                    statusText = 'Error';
                    break;
                case 'running':
                    statusIcon = '🔄';
                    statusText = 'En ejecución (GUI activa)';
                    break;
                default:
                    statusIcon = '❓';
                    statusText = entry.status;
            }

            // Información del entorno Python y ejecutable
            const envInfo = entry.python_env ? ` • ${entry.python_env}` : '';
            const executableType = entry.executable_type || 'python.exe';
            const executableIcon = executableType.includes('pythonw') ? '🚀' : '🖥️';

            // Botones para procesos en ejecución
            const processButtons = entry.status === 'running' && entry.pid ? `
                <div class="flex gap-1 mt-2">
                    <button onclick="launcherManager.focusProcess(${entry.pid})"
                            class="text-blue-500 hover:underline text-xs">
                        📍 Activar
                    </button>
                    <button onclick="launcherManager.terminateProcess(${entry.pid})"
                            class="text-red-500 hover:underline text-xs">
                        ❌ Cerrar
                    </button>
                </div>
            ` : '';

            const item = document.createElement('div');
            item.className = `history-item ${statusClass}`;
            item.innerHTML = `
                <div class="flex justify-between items-start">
                    <div>
                        <span class="font-medium">${entry.script_name.replace('.py', '')}</span>
                        <span class="text-sm text-gray-500 ml-2">${groupName}${envInfo}</span>
                    </div>
                    <span class="text-xs text-gray-400">${timeAgo}</span>
                </div>
                <div class="text-sm text-gray-600 mt-1">
                    ${statusIcon} ${statusText}
                    ${entry.execution_time ? ` • ${entry.execution_time.toFixed(1)}s` : ''}
                    ${entry.arguments && entry.arguments.length > 0 ? ` • Con argumentos` : ''}
                </div>
                <div class="text-xs text-gray-500 mt-1">
                    ${executableIcon} ${executableType}${entry.working_directory ? ` • ${entry.working_directory}` : ''}
                </div>
                ${processButtons}
            `;
            historyList.appendChild(item);
        });
    }

    // ... métodos existentes sin cambios ...

    // El resto de métodos permanecen igual
    filterByCategory(category) {
        this.currentFilter = category;

        // Actualizar botones activos
        document.querySelectorAll('.category-btn').forEach(btn => {
            btn.classList.remove('active');
        });
        document.querySelector(`[data-category="${category}"]`).classList.add('active');

        // Filtrar grupos en el selector
        const selector = document.getElementById('launcher-group-select');
        Array.from(selector.options).forEach(option => {
            if (option.value === '') return;
            option.style.display = (category === 'all' || option.dataset.category === category) ? '' : 'none';
        });

        // Re-renderizar scripts si hay grupo seleccionado
        if (this.currentGroup) {
            this.renderScripts();
        }
    }

    async toggleFavorite(groupId, scriptName) {
        try {
            const response = await fetch('/api/launcher-favorites', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    group_id: groupId,
                    script_name: scriptName
                })
            });

            const result = await response.json();
            if (result.status === 'success') {
                const favoriteId = `${groupId}_${scriptName}`;
                if (result.action === 'added') {
                    this.favorites.add(favoriteId);
                } else {
                    this.favorites.delete(favoriteId);
                }

                // Recargar datos y re-renderizar
                await this.loadFavorites();
                this.renderScripts();
                this.updateFavoritesCount();
            }
        } catch (error) {
            console.error('Error toggling favorite:', error);
        }
    }

    showArgsModal(scriptName, displayName) {
        const modal = document.getElementById('script-args-modal');
        const scriptDisplayElement = document.getElementById('script-display-name');
        const argsInput = document.getElementById('script-args-input');
        const workingDirInput = document.getElementById('script-working-dir');

        if (modal && scriptDisplayElement && argsInput) {
            scriptDisplayElement.textContent = displayName;
            argsInput.value = '';
            workingDirInput.value = ''; // Limpiar directorio de trabajo
            modal.classList.remove('hidden');

            // Guardar datos para uso posterior
            modal.dataset.scriptName = scriptName;
            modal.dataset.groupId = this.currentGroup.id;
        }
    }

    async executeScript(scriptName, args = [], workingDir = null, usePythonw = false) {
        if (!this.currentGroup) return;

        try {
            const requestData = {
                group_id: this.currentGroup.id,
                script_name: scriptName,
                args: args,
                use_pythonw: usePythonw
            };

            // Agregar directorio de trabajo si se especifica
            if (workingDir && workingDir.trim()) {
                requestData.working_dir = workingDir.trim();
            }

            const response = await fetch('/api/execute-gui-script', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(requestData)
            });

            const result = await response.json();
            if (result.status === 'success') {
                // Recargar historial
                await this.loadHistory();
            }
        } catch (error) {
            console.error('Error executing script:', error);
        }
    }

    // Función para buscar directorio de trabajo
    browseWorkingDirectory() {
        fetch('/api/browse-directories')
            .then(response => response.json())
            .then(data => {
                if (data.status === 'success') {
                    document.getElementById('script-working-dir').value = data.path;
                }
            })
            .catch(error => {
                console.error('Error browsing directory:', error);
            });
    }

    async renderFavorites(favorites) {
        const favoritesList = document.getElementById('favorites-list');
        const favoritesPanel = document.getElementById('favorites-panel');

        if (!favoritesList || !favoritesPanel) return;

        if (favorites.length === 0) {
            favoritesPanel.classList.add('empty');
            return;
        }

        favoritesPanel.classList.remove('empty');
        favoritesList.innerHTML = '';

        // Cambiar a diseño de grid para cards más compactas
        favoritesList.className = 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3';

        // Obtener metadatos de todos los scripts favoritos
        for (const fav of favorites.slice(0, 6)) { // Mostrar hasta 6 favoritos en grid
            const group = this.groups.find(g => g.id === fav.group_id);
            if (!group) continue;

            try {
                // Obtener metadatos del script para mostrar el display_name
                const response = await fetch(`/api/launcher-script-metadata/${fav.group_id}/${fav.script_name}`);
                const metadata = await response.json();
                const displayName = metadata.display_name || fav.script_name.replace('.py', '');

                const card = document.createElement('div');
                card.className = 'bg-white border border-yellow-300 rounded-lg p-3 hover:shadow-md transition-all duration-200 hover:border-yellow-400';

                // Crear contenedor para el icono que se actualizará dinámicamente
                const iconId = `fav-icon-${fav.group_id}`;

                card.innerHTML = `
                    <div class="flex items-start justify-between mb-2">
                        <div class="flex items-center min-w-0 flex-1">
                            <div id="${iconId}" class="group-icon-small default mr-2 flex-shrink-0">
                                ${this.getDefaultIconForCategory(group.category)}
                            </div>
                            <div class="min-w-0 flex-1">
                                <div class="font-medium text-sm text-gray-900 truncate" title="${displayName}">
                                    ${displayName}
                                </div>
                                <div class="text-xs text-gray-500 truncate" title="${group.name}">
                                    ${group.name}
                                </div>
                            </div>
                        </div>
                        <button class="favorite-star active text-yellow-500 ml-2 flex-shrink-0"
                                onclick="launcherManager.toggleFavorite('${fav.group_id}', '${fav.script_name}')"
                                title="Quitar de favoritos">
                            ⭐
                        </button>
                    </div>
                    <div class="flex gap-1">
                        <button class="bg-blue-500 text-white px-2 py-1 rounded text-xs hover:bg-blue-600 flex-1"
                                onclick="launcherManager.executeFavoriteScript('${fav.group_id}', '${fav.script_name}')"
                                title="Ejecutar script">
                            🖥️ Ejecutar
                        </button>
                        <button class="bg-green-500 text-white px-2 py-1 rounded text-xs hover:bg-green-600 flex-1"
                                onclick="launcherManager.executeFavoriteScriptSilent('${fav.group_id}', '${fav.script_name}')"
                                title="Ejecutar sin ventana de consola">
                            🔇 Silencioso
                        </button>
                    </div>
                `;
                favoritesList.appendChild(card);

                // Intentar cargar el icono personalizado del grupo después de agregar la card
                this.loadGroupIconForFavorite(iconId, fav.group_id, group.category);

            } catch (error) {
                console.error('Error loading script metadata for favorite:', error);
                // Fallback al nombre del archivo
                const card = document.createElement('div');
                card.className = 'bg-white border border-yellow-300 rounded-lg p-3 hover:shadow-md transition-all duration-200 hover:border-yellow-400';

                const iconId = `fav-icon-${fav.group_id}`;

                card.innerHTML = `
                    <div class="flex items-start justify-between mb-2">
                        <div class="flex items-center min-w-0 flex-1">
                            <div id="${iconId}" class="group-icon-small default mr-2 flex-shrink-0">
                                ${this.getDefaultIconForCategory(group.category)}
                            </div>
                            <div class="min-w-0 flex-1">
                                <div class="font-medium text-sm text-gray-900 truncate" title="${fav.script_name.replace('.py', '')}">
                                    ${fav.script_name.replace('.py', '')}
                                </div>
                                <div class="text-xs text-gray-500 truncate" title="${group.name}">
                                    ${group.name}
                                </div>
                            </div>
                        </div>
                        <button class="favorite-star active text-yellow-500 ml-2 flex-shrink-0"
                                onclick="launcherManager.toggleFavorite('${fav.group_id}', '${fav.script_name}')"
                                title="Quitar de favoritos">
                            ⭐
                        </button>
                    </div>
                    <div class="flex gap-1">
                        <button class="bg-blue-500 text-white px-2 py-1 rounded text-xs hover:bg-blue-600 flex-1"
                                onclick="launcherManager.executeFavoriteScript('${fav.group_id}', '${fav.script_name}')"
                                title="Ejecutar script">
                            🖥️ Ejecutar
                        </button>
                        <button class="bg-green-500 text-white px-2 py-1 rounded text-xs hover:bg-green-600 flex-1"
                                onclick="launcherManager.executeFavoriteScriptSilent('${fav.group_id}', '${fav.script_name}')"
                                title="Ejecutar sin ventana de consola">
                            🔇 Silencioso
                        </button>
                    </div>
                `;
                favoritesList.appendChild(card);

                // Intentar cargar el icono personalizado del grupo
                this.loadGroupIconForFavorite(iconId, fav.group_id, group.category);
            }
        }
    }

    // Nuevo método para cargar iconos específicos de grupo en favoritos
    loadGroupIconForFavorite(iconElementId, groupId, fallbackCategory) {
        const iconElement = document.getElementById(iconElementId);
        if (!iconElement) return;

        // Intentar cargar icono personalizado
        const img = document.createElement('img');
        img.src = `/api/group-icon/launcher/${groupId}`;
        img.className = 'w-7 h-7 rounded object-cover';
        img.onerror = () => {
            // Fallback a icono por defecto basado en categoría
            iconElement.innerHTML = this.getDefaultIconForCategory(fallbackCategory);
            iconElement.className = 'group-icon-small default mr-2 flex-shrink-0';
        };
        img.onload = () => {
            // Reemplazar con imagen personalizada
            iconElement.innerHTML = '';
            iconElement.className = 'mr-2 flex-shrink-0 flex items-center justify-center';
            iconElement.appendChild(img);
        };
    }

    // Nuevo método para ejecutar favoritos en modo silencioso
    async executeFavoriteScriptSilent(groupId, scriptName) {
        // Cambiar al grupo correcto si no está seleccionado
        if (!this.currentGroup || this.currentGroup.id !== groupId) {
            document.getElementById('launcher-group-select').value = groupId;
            localStorage.setItem('launcher-selected-group', groupId);
            await this.loadLauncherScripts();
        }

        this.executeScript(scriptName, [], null, true); // true para usar pythonw
    }

    async executeFavoriteScript(groupId, scriptName) {
        // Cambiar al grupo correcto si no está seleccionado
        if (!this.currentGroup || this.currentGroup.id !== groupId) {
            document.getElementById('launcher-group-select').value = groupId;
            localStorage.setItem('launcher-selected-group', groupId);
            await this.loadLauncherScripts();
        }

        this.executeScript(scriptName);
    }

    getTimeAgo(dateString) {
        const date = new Date(dateString);
        const now = new Date();
        const diffMs = now - date;
        const diffMinutes = Math.floor(diffMs / 60000);

        if (diffMinutes < 1) return 'ahora';
        if (diffMinutes < 60) return `hace ${diffMinutes}m`;
        if (diffMinutes < 1440) return `hace ${Math.floor(diffMinutes / 60)}h`;
        return `hace ${Math.floor(diffMinutes / 1440)}d`;
    }

    updateFavoritesCount() {
        const countElement = document.getElementById('favorites-count');
        if (countElement) {
            countElement.textContent = `${this.favorites.size} favoritos`;
        }
    }

    async clearLauncherHistory() {
        // Eliminada la confirmación - directamente procede a limpiar
        try {
            const response = await fetch('/api/launcher-history', {
                method: 'DELETE'
            });

            const result = await response.json();
            if (result.status === 'success') {
                this.history = [];
                this.renderHistory();
                console.log('Historial del launcher limpiado');
            }
        } catch (error) {
            console.error('Error clearing history:', error);
        }
    }

    // === GESTIÓN DE GRUPOS ===

    openGroupEditor() {
        const modal = document.getElementById('group-editor-modal');
        if (modal) {
            this.currentEditingGroup = null;
            this.clearGroupForm();
            this.renderExistingGroups();
            modal.classList.remove('hidden');
        }
    }

    closeGroupEditor() {
        const modal = document.getElementById('group-editor-modal');
        if (modal) {
            modal.classList.add('hidden');
            this.currentEditingGroup = null;
        }
    }

    editGroup(groupId) {
        const group = this.groups.find(g => g.id === groupId);
        if (!group) return;

        this.currentEditingGroup = group;
        this.populateGroupForm(group);
        document.getElementById('delete-group-btn').style.display = 'block';
    }

    async deleteGroup() {
        if (!this.currentEditingGroup) return;

        if (!confirm(`¿Estás seguro de que quieres eliminar el grupo "${this.currentEditingGroup.name}"?`)) return;

        try {
            const response = await fetch(`/api/launcher-groups/${this.currentEditingGroup.id}`, {
                method: 'DELETE'
            });

            const result = await response.json();
            if (result.status === 'success') {
                await this.loadGroups();
                this.closeGroupEditor();
                this.renderInterface();

                // Limpiar selección si era el grupo actual
                if (this.currentGroup && this.currentGroup.id === this.currentEditingGroup.id) {
                    document.getElementById('launcher-group-select').value = '';
                    this.currentGroup = null;
                    this.scripts = [];
                    this.renderScripts();
                    this.updateManageScriptsButton(false);
                    this.updateEditorButtons(false); // Ocultar botones de editor
                }
            } else {
                alert(`Error: ${result.message}`);
            }
        } catch (error) {
            console.error('Error deleting group:', error);
            alert('Error al eliminar el grupo');
        }
    }

    browseGroupDirectory() {
        // Similar a la función existente pero para el formulario de grupos
        fetch('/api/browse-directories')
            .then(response => response.json())
            .then(data => {
                if (data.status === 'success') {
                    document.getElementById('group-directory').value = data.path;
                }
            })
            .catch(error => {
                console.error('Error browsing directory:', error);
            });
    }

    // Nueva función genérica para abrir en editor
    async openGroupInEditor(editorCode, groupSystem, groupId) {
        if (!groupId) {
            alert('Selecciona un grupo primero');
            return;
        }

        const editorName = editorCode.toUpperCase();

        try {
            const response = await fetch(`/api/open-editor/${editorCode}/${groupSystem}/${groupId}`, {
                method: 'POST'
            });

            if (!response.ok) {
                // If response is not OK, it might not be JSON (e.g., Flask error page)
                const errorText = await response.text();
                console.error(`Error al abrir ${editorName}: HTTP ${response.status}`, errorText);
                alert(`Error al abrir ${editorName}: ${response.status} ${response.statusText}\n${errorText.substring(0, 200)}...`); // Show limited error text
            } else {
                const result = await response.json(); // Now it's safer to parse JSON
                if (result.status === 'success') {
                    console.log(result.message);
                    // Opcional: mostrar un toast/notificación de éxito
                    // showToast(result.message, 'success');
                } else {
                    console.error(`Error al abrir ${editorName}:`, result.message);
                    alert(`Error: ${result.message || 'Error desconocido.'}`);
                }
            }
        } catch (error) {
            console.error(`Error en la llamada fetch para open-editor (${editorName}):`, error);
            alert(`Error de red o del cliente al intentar abrir ${editorName}.`);
        }
    }


    async focusProcess(pid) {
        try {
            const response = await fetch(`/api/launcher-process-focus/${pid}`, {
                method: 'POST'
            });
            const result = await response.json();

            if (result.status === 'success') {
                console.log(result.message);
            } else {
                alert(`Error: ${result.message}`);
            }
        } catch (error) {
            console.error('Error focusing process:', error);
            alert('Error activando proceso');
        }
    }

    async terminateProcess(pid) {
        // Eliminada la confirmación - directamente procede a cerrar
        try {
            const response = await fetch(`/api/launcher-process-terminate/${pid}`, {
                method: 'POST'
            });
            const result = await response.json();

            if (result.status === 'success') {
                console.log(result.message);
                // Recargar historial para actualizar estado
                await this.loadHistory();
            } else {
                alert(`Error: ${result.message}`);
            }
        } catch (error) {
            console.error('Error terminating process:', error);
            alert('Error cerrando proceso');
        }
    }

    // Nueva función para abrir carpeta del grupo launcher
    async openGroupFolder() {
        if (!this.currentGroup) {
            alert('Selecciona un grupo primero');
            return;
        }

        try {
            const response = await fetch(`/api/open-group-folder/launcher/${this.currentGroup.id}`, {
                method: 'POST'
            });

            const result = await response.json();
            if (result.status === 'success') {
                console.log(`Carpeta abierta: ${result.path}`);
            } else {
                alert(`Error al abrir carpeta: ${result.message}`);
            }
        } catch (error) {
            console.error('Error opening folder:', error);
            alert('Error al comunicarse con el servidor');
        }
    }

    // Nueva función para copiar path del grupo launcher
    async copyGroupPath() {
        if (!this.currentGroup) {
            alert('Selecciona un grupo primero');
            return;
        }

        try {
            const response = await fetch(`/api/get-group-path/launcher/${this.currentGroup.id}`);
            const result = await response.json();

            if (result.status === 'success') {
                // Copiar al portapapeles usando la API moderna
                if (navigator.clipboard && navigator.clipboard.writeText) {
                    await navigator.clipboard.writeText(result.path);
                    console.log('Path copiado al portapapeles');
                } else {
                    // Fallback para navegadores más antiguos
                    const textArea = document.createElement('textarea');
                    textArea.value = result.path;
                    document.body.appendChild(textArea);
                    textArea.focus();
                    textArea.select();

                    try {
                        document.execCommand('copy');
                        console.log('Path copiado al portapapeles');
                    } catch (err) {
                        console.error('Error copying to clipboard:', err);
                        alert(`Error al copiar. Path: ${result.path}`);
                    }

                    document.body.removeChild(textArea);
                }
            } else {
                alert(`Error al obtener path: ${result.message}`);
            }
        } catch (error) {
            console.error('Error getting path:', error);
            alert('Error al comunicarse con el servidor');
        }
    }
}

// === FUNCIONES GLOBALES ===

// Función para cambiar entre tabs
function switchTab(tabName) {
    // Cambiar tabs activos
    document.querySelectorAll('.tab-button').forEach(btn => {
        btn.classList.remove('active');
    });
    document.getElementById(`${tabName}-tab`).classList.add('active');

    // Cambiar contenido
    document.querySelectorAll('.tab-content').forEach(content => {
        content.classList.add('hidden');
    });
    document.getElementById(`${tabName}-content`).classList.remove('hidden');

    // Inicializar launcher si es la primera vez
    if (tabName === 'launcher' && !window.launcherManager) {
        window.launcherManager = new LauncherManager();
        window.launcherManager.init();
    }

    // Inicializar C# launcher si es la primera vez
    if (tabName === 'csharp') {
        if (!window.csharpLauncherManager) {
            console.error('csharpLauncherManager not found! Make sure csharp_launcher.js is loaded.');
            return;
        }
        if (!window.csharpLauncherManager.initialized) {
            window.csharpLauncherManager.init();
        }
    }

    // Inicializar Python launcher si es la primera vez
    if (tabName === 'python') {
        if (typeof initPythonLauncher === 'function') {
            initPythonLauncher();
        } else {
            console.error('initPythonLauncher function not found! Make sure python_launcher.js is loaded.');
        }
    }
}

// Funciones para modales
function openGroupEditor() {
    if (window.launcherManager) {
        window.launcherManager.openGroupEditor();
    }
}

function closeGroupEditor() {
    if (window.launcherManager) {
        window.launcherManager.closeGroupEditor();
    }
}

function deleteGroup() {
    if (window.launcherManager) {
        window.launcherManager.deleteGroup();
    }
}

function browseGroupDirectory() {
    if (window.launcherManager) {
        window.launcherManager.browseGroupDirectory();
    }
}

function filterByCategory(category) {
    if (window.launcherManager) {
        window.launcherManager.filterByCategory(category);
    }
}

function loadLauncherScripts() {
    if (window.launcherManager) {
        window.launcherManager.loadLauncherScripts();
    }
}

function clearLauncherHistory() {
    if (window.launcherManager) {
        window.launcherManager.clearLauncherHistory();
    }
}

// Funciones para gestión de scripts
function openScriptManager() {
    if (window.launcherManager) {
        window.launcherManager.openScriptManager();
    }
}

function closeScriptManager() {
    if (window.launcherManager) {
        window.launcherManager.closeScriptManager();
    }
}

function closeScriptMetadataEditor() {
    if (window.launcherManager) {
        window.launcherManager.closeScriptMetadataEditor();
    }
}

// Funciones para modal de argumentos
function closeArgsModal() {
    const modal = document.getElementById('script-args-modal');
    if (modal) {
        modal.classList.add('hidden');
    }
}

function executeWithArgs() {
    const modal = document.getElementById('script-args-modal');
    const argsInput = document.getElementById('script-args-input');
    const workingDirInput = document.getElementById('script-working-dir');
    const executionTypeInputs = document.getElementsByName('execution-type');

    if (modal && argsInput && window.launcherManager) {
        const scriptName = modal.dataset.scriptName;
        const args = argsInput.value.trim().split(/\s+/).filter(arg => arg.length > 0);
        const workingDir = workingDirInput.value.trim();

        // Leer el tipo de ejecución seleccionado
        let usePythonw = false;
        for (const input of executionTypeInputs) {
            if (input.checked) {
                usePythonw = input.value === 'true';
                break;
            }
        }

        window.launcherManager.executeScript(scriptName, args, workingDir, usePythonw);
        closeArgsModal();
    }
}

function browseWorkingDirectory() {
    if (window.launcherManager) {
        window.launcherManager.browseWorkingDirectory();
    }
}

// Funciones para modal de descripción
function closeDescriptionModal() {
    const modal = document.getElementById('script-description-modal');
    if (modal) {
        modal.classList.add('hidden');
    }
}

function closeMarkdownViewer() {
    const modal = document.getElementById('markdown-viewer-modal');
    if (modal) {
        modal.classList.add('hidden');
    }
}

// Inicialización cuando se carga la página
document.addEventListener('DOMContentLoaded', function () {
    console.log('Launcher JS loaded');
});

// Función para colapsar/expandir el historial
function toggleHistoryPanel() {
    const historyList = document.getElementById('history-list');
    const toggleIcon = document.getElementById('history-toggle-icon');

    if (historyList && toggleIcon) {
        if (historyList.classList.contains('hidden')) {
            // Expandir
            historyList.classList.remove('hidden');
            toggleIcon.textContent = '▼';
        } else {
            // Colapsar
            historyList.classList.add('hidden');
            toggleIcon.textContent = '▶';
        }
    }
}
