let currentGroup;

// Registro de procesos en ejecución para scripts de configuración
let runningConfigScripts = new Set();

// Initialize WebSocket connection
let socket = null; // Define socket en un alcance accesible (p.ej., globalmente o en el scope del módulo)

function initWebSocket() {
    // Comprobar si ya existe un socket y está abierto o conectándose
    if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) {
        console.log("WebSocket ya está abierto o conectándose.");
        return; // No crear una nueva conexión
    }

    // Determinar URL del WebSocket (ws:// o wss://)
    const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const wsUrl = `${wsProtocol}//${window.location.host}/ws`;

    console.log("Inicializando conexión WebSocket a:", wsUrl);
    socket = new WebSocket(wsUrl);

    socket.onopen = () => {
        console.log('Conexión WebSocket establecida');
    };

    socket.onmessage = (event) => {
        // console.log('Mensaje del servidor:', event.data); // Opcional: para depuración
        addLogLine(event.data); // Llama a la función que ya tienes
    };

    socket.onerror = (error) => {
        console.error('Error WebSocket:', error);
        addLogLine('Error de conexión WebSocket.'); // Informar al usuario
    };

    socket.onclose = (event) => {
        console.log('Conexión WebSocket cerrada:', event.code, event.reason);
        // Opcional: intentar reconectar o informar al usuario
        if (!event.wasClean) {
            addLogLine('Conexión WebSocket perdida. Intente recargar la página.');
        }
        socket = null; // Restablecer la variable socket después de cerrar
    };
}

// Load configurations for all levels
async function loadConfigs() {
    const group = currentGroup;
    console.log('Loading configs for group:', group);

    if (!group) {
        console.error('No group selected');
        return;
    }

    try {
        // Cargar niveles 1 y 2
        for (let level of [1, 2]) {
            console.log(`Loading level ${level} config...`);
            const response = await fetch(`/api/config/${level}?group=${group}`);
            if (!response.ok) throw new Error(`Error loading level ${level} config`);
            const data = await response.json();
            console.log(`Level ${level} data:`, data);
            await renderForm(`level${level}-form`, data);
        }

        // Cargar nivel 3 solo si hay directorio de trabajo
        const workingDirResponse = await fetch(`/api/working-directory/${group}`);
        const workingDirResult = await workingDirResponse.json();

        if (workingDirResult.status === 'success' && workingDirResult.path) {
            console.log('Loading level 3 config...');
            const response = await fetch(`/api/config/3?group=${group}`);
            if (!response.ok) throw new Error('Error loading level 3 config');
            const data = await response.json();
            console.log('Level 3 data:', data);
            await renderForm('level3-form', data);

            // Actualizar input del directorio de trabajo
            document.getElementById('working-directory').value = workingDirResult.path;
        }

        // Cargar scripts disponibles
        await loadScripts(group);

    } catch (error) {
        console.error('Error loading configs:', error);
    }
}

// --- Funciones para Editar Detalles del Script ---

async function editScriptDetails(group, scriptFilename) {
    console.log(`[1] editScriptDetails called for: group=${group}, script=${scriptFilename}`); // Log inicial
    try {
        console.log('[2] Fetching script details...'); // Log antes del fetch
        const response = await fetch(`/api/script-details/${group}/${scriptFilename}`);
        console.log('[3] Fetch response received:', response); // Log después del fetch
        if (!response.ok) {
            console.error(`[!] Fetch error: ${response.status} ${response.statusText}`); // Log si la respuesta no es OK
            throw new Error(`Error fetching script details: ${response.statusText}`);
        }
        console.log('[4] Parsing JSON response...'); // Log antes de parsear JSON
        const details = await response.json();
        console.log('[5] Script details received:', details); // Log con los detalles

        // Poblar el modal
        document.getElementById('edit-script-group').value = group;
        document.getElementById('edit-script-filename').value = scriptFilename;
        document.getElementById('edit-script-filename-display').textContent = scriptFilename; // Mostrar nombre de archivo
        document.getElementById('edit-script-display-name').value = details.display_name || '';
        document.getElementById('edit-script-short-description').value = details.short_description || ''; // Poblar descripción corta
        document.getElementById('edit-script-long-description').value = details.long_description || '';
        document.getElementById('edit-script-hidden').checked = details.hidden || false;

        console.log('[6] Populated modal fields.'); // Log después de poblar
        // Mostrar el modal
        document.getElementById('script-editor-modal').classList.remove('hidden');
        console.log('[7] Modal should be visible now.'); // Log final

    } catch (error) {
        console.error('[!] Error in editScriptDetails:', error); // Log en el catch
        alert(`Error al cargar detalles del script: ${error.message}`);
    }
}

function closeScriptEditorModal() {
    document.getElementById('script-editor-modal').classList.add('hidden');
    // Limpiar campos si es necesario (opcional)
    // document.getElementById('edit-script-display-name').value = '';
    // document.getElementById('edit-script-long-description').value = '';
    // document.getElementById('edit-script-hidden').checked = false;
}

async function saveScriptDetails() {
    const group = document.getElementById('edit-script-group').value;
    const scriptFilename = document.getElementById('edit-script-filename').value;
    const updatedDetails = {
        display_name: document.getElementById('edit-script-display-name').value,
        short_description: document.getElementById('edit-script-short-description').value, // Recoger descripción corta
        long_description: document.getElementById('edit-script-long-description').value,
        hidden: document.getElementById('edit-script-hidden').checked
    };

    try {
        const response = await fetch(`/api/script-details/${group}/${scriptFilename}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(updatedDetails)
        });
        const result = await response.json();
        if (!response.ok || result.status !== 'success') {
            throw new Error(result.message || `Error guardando detalles: ${response.statusText}`);
        }
        closeScriptEditorModal();
        await loadScripts(currentGroup); // Recargar la lista de scripts
        showToast('Detalles del script guardados con éxito.');

    } catch (error) {
        console.error('Error saving script details:', error);
        alert(`Error al guardar detalles del script: ${error.message}`);
    }
}

// Load and display available scripts
async function loadScripts(group) {
    if (!group) {
        console.warn("loadScripts called without group");
        document.getElementById('scripts-list').innerHTML = '<p class="text-gray-500">Selecciona un grupo para ver los scripts.</p>';
        return;
    }
    const response = await fetch(`/api/scripts/${group}`);
    const scripts = await response.json();
    const container = document.getElementById('scripts-list');
    container.innerHTML = ''; // Limpiar contenedor antes de añadir nuevos elementos

    scripts.forEach(script => {
        const div = document.createElement('div');
        div.className = 'script-item p-4 border rounded bg-white shadow-sm flex justify-between items-start gap-4';
        div.innerHTML = `
            <div>
                <div class="font-bold text-lg mb-1">${script.name}</div>
                <div class="flex items-center gap-2">
                    <span class="text-gray-600 text-sm">${script.description}</span>
                    ${script.long_description ? `
                        <button class="toggle-long-desc-button text-blue-500 hover:text-blue-700 p-0.5 rounded" data-target-id="long-desc-${script.filename}" title="Mostrar/Ocultar detalles">
                            <svg class="w-4 h-4 chevron-down" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
                            </svg>
                            <svg class="w-4 h-4 chevron-up hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>
                            </svg>
                        </button>
                    ` : ''}
                </div>
                <div id="long-desc-${script.filename}" class="long-description-content mt-2 border-t pt-2 hidden">
                    ${script.long_description ? (() => { // Self-invoking function to handle markdown rendering
                if (typeof window.markdownit === 'undefined') { // Check if markdownit is loaded
                    console.error("markdown-it library not loaded!");
                    return `<p class="text-red-500">Error: Librería Markdown no cargada.</p><pre>${script.long_description}</pre>`; // Fallback: show raw text
                }
                // Create instance and render
                const md = window.markdownit();
                const renderedHtml = md.render(script.long_description); // Renderizar
                return renderedHtml;
            })() : ''}
                </div>
            </div>
            <div class="flex items-center gap-2 flex-shrink-0">
                 <div class="flex flex-col items-center">
                    <div class="flex gap-1">
                        <button data-filename="${script.filename}"
                                class="bg-green-500 hover:bg-green-600 text-white px-2 py-1 rounded text-sm execute-button"
                                title="Ejecutar script">
                            ▶
                        </button>
                        <button data-filename="${script.filename}"
                                class="bg-red-500 hover:bg-red-600 text-white px-2 py-1 rounded text-sm stop-button disabled:opacity-50 disabled:cursor-not-allowed"
                                disabled
                                title="Detener script">
                            ⏹
                        </button>
                    </div>
                    <div class="text-xs text-gray-500 mt-1 truncate w-20 text-center" title="${script.filename}">${script.filename}</div>
                </div>
                <button data-group="${group}" data-filename="${script.filename}"
                        class="p-1 rounded text-gray-500 hover:bg-gray-200 hover:text-gray-700 edit-button" title="Editar Detalles">
                    <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
                    </svg>
                </button>
            </div>
        `;
        container.appendChild(div);

        // Añadir event listeners a los botones recién creados
        const executeButton = div.querySelector('.execute-button');
        executeButton.addEventListener('click', () => {
            executeScript(script.filename);
        });

        const stopButton = div.querySelector('.stop-button');
        stopButton.addEventListener('click', () => {
            stopScript(script.filename);
        });

        const editButton = div.querySelector('.edit-button');
        editButton.addEventListener('click', () => {
            editScriptDetails(group, script.filename);
        });

        // Añadir event listener para el botón de descripción larga (si existe)
        const toggleDescButton = div.querySelector('.toggle-long-desc-button');
        if (toggleDescButton) {
            toggleDescButton.addEventListener('click', (e) => {
                const button = e.currentTarget;
                const targetId = button.dataset.targetId;
                const targetElement = document.getElementById(targetId);
                if (targetElement) {
                    targetElement.classList.toggle('hidden');
                    button.querySelector('.chevron-down').classList.toggle('hidden');
                    button.querySelector('.chevron-up').classList.toggle('hidden');
                }
            });
        }
    });
}

// Execute a script
async function executeScript(scriptName) {
    // REMOVE this line - let the backend log the start via WebSocket
    // addLogLine(`\nEjecutando script: ${scriptName}...\n`);

    // Marcar script como en ejecución
    runningConfigScripts.add(scriptName);
    updateScriptButtons(scriptName, true);

    try {
        const response = await fetch('/api/execute_script', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ group: currentGroup, script: scriptName }) // scriptName aquí es el filename real
        });

        // Check for HTTP errors during the *request* itself
        if (!response.ok) {
            const errorText = await response.text();
            console.error(`Error initiating script execution request: ${response.status} ${response.statusText}`, errorText);
            // Log only the request error, not script execution errors which come via WebSocket
            addLogLine(`\nError al iniciar la petición del script: ${response.status} ${errorText}\n`);
            
            // Desmarcar script si falló el inicio
            runningConfigScripts.delete(scriptName);
            updateScriptButtons(scriptName, false);
            return; // Stop if the request failed
        }

        // REMOVE logging the result/error here - let the backend log via WebSocket
        // const result = await response.json(); // Still potentially need to read body if not done elsewhere
        // if (result.error) {
        //     addLogLine(`\nError: ${result.error}\n`);
        // }

        // Script output and final status/errors will arrive via WebSocket messages
        // handled by socket.onmessage -> addLogLine

        // Nota: El script se desmarcará cuando termine (en el backend deberíamos enviar una señal de finalización)
        // Por ahora, lo desmarcaremos después de un tiempo o cuando el usuario haga clic en stop

    } catch (error) {
        console.error('Error in executeScript fetch:', error);
        addLogLine(`\nError de red o JavaScript al intentar ejecutar el script: ${error.message}\n`);
        
        // Desmarcar script si hubo error
        runningConfigScripts.delete(scriptName);
        updateScriptButtons(scriptName, false);
    }
}

// Stop a script
async function stopScript(scriptName) {
    try {
        addLogLine(`\nDeteniendo script: ${scriptName}...\n`);
        
        const response = await fetch('/api/stop_script', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ group: currentGroup, script: scriptName })
        });

        if (!response.ok) {
            const errorText = await response.text();
            console.error(`Error stopping script: ${response.status} ${response.statusText}`, errorText);
            addLogLine(`\nError al detener el script: ${response.status} ${errorText}\n`);
            return;
        }

        const result = await response.json();
        if (result.error) {
            addLogLine(`\nError al detener script: ${result.error}\n`);
        } else {
            addLogLine(`\nScript ${scriptName} detenido con éxito.\n`);
        }

        // Desmarcar script como en ejecución
        runningConfigScripts.delete(scriptName);
        updateScriptButtons(scriptName, false);

    } catch (error) {
        console.error('Error stopping script:', error);
        addLogLine(`\nError de red al intentar detener el script: ${error.message}\n`);
    }
}

// Actualizar estado de botones (ejecutar/stop) para un script
function updateScriptButtons(scriptName, isRunning) {
    const scriptItem = document.querySelector(`[data-filename="${scriptName}"]`).closest('.script-item');
    if (!scriptItem) return;

    const executeButton = scriptItem.querySelector('.execute-button');
    const stopButton = scriptItem.querySelector('.stop-button');

    if (isRunning) {
        executeButton.disabled = true;
        executeButton.classList.add('opacity-50', 'cursor-not-allowed');
        stopButton.disabled = false;
        stopButton.classList.remove('opacity-50', 'cursor-not-allowed');
    } else {
        executeButton.disabled = false;
        executeButton.classList.remove('opacity-50', 'cursor-not-allowed');
        stopButton.disabled = true;
        stopButton.classList.add('opacity-50', 'cursor-not-allowed');
    }
}

// Función para detectar cuando un script ha terminado mediante mensajes de WebSocket
function handleScriptCompletion(message) {
    // Buscar patrones que indiquen que un script ha terminado
    const completionPatterns = [
        /Ejecución de (.+?) finalizada/,
        /Script (.+?) detenido/,
        /ERROR FATAL.*?en (.+?):/
    ];
    
    for (const pattern of completionPatterns) {
        const match = message.match(pattern);
        if (match) {
            const scriptName = match[1];
            if (runningConfigScripts.has(scriptName)) {
                runningConfigScripts.delete(scriptName);
                updateScriptButtons(scriptName, false);
                console.log(`Script ${scriptName} marcado como terminado`);
            }
            break;
        }
    }
}

// Form rendering functionality
async function renderForm(containerId, data) {
    console.log(`Rendering form for ${containerId} with data:`, data); // Debug line
    const container = document.getElementById(containerId);
    const level = containerId.replace('level', '').split('-')[0];

    try {
        const schemaResponse = await fetch(`/api/schema/${level}?group=${currentGroup}`);
        const schema = await schemaResponse.json();
        console.log(`Schema for level ${level}:`, schema); // Debug line

        if (!schema || !schema.properties || Object.keys(schema.properties).length === 0) {
            container.innerHTML = '<p class="text-gray-500">No hay esquema definido para este nivel.</p>';
            return;
        }

        // Guardar el estado del botón si existe
        const existingButton = document.getElementById(`save-config-${level}`);
        const buttonState = existingButton ? {
            text: existingButton.innerText,
            className: existingButton.className,
            disabled: existingButton.disabled
        } : null;

        container.innerHTML = `
            <form id="config-form-${level}" class="space-y-4">
                ${generateFormFields(schema, data || {}, '', level)}
            </form>
            <div class="flex justify-end mt-4">
                <button id="save-config-${level}" onclick="saveConfig(${level})" 
                        class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded transition-colors duration-300">
                    Guardar Configuración
                </button>
            </div>
        `;

        // Restaurar el estado del botón si existía
        if (buttonState) {
            const newButton = document.getElementById(`save-config-${level}`);
            newButton.innerText = buttonState.text;
            newButton.className = buttonState.className;
            newButton.disabled = buttonState.disabled;
        }

    } catch (error) {
        console.error(`Error rendering form ${containerId}:`, error);
        container.innerHTML = '<p class="text-red-500">Error cargando el esquema.</p>';
    }
}

function generateFormFields(schema, data, prefix, level) {
    console.log('Generating fields with data:', { schema, data, prefix, level }); // Debug line
    let html = '';

    if (!schema.properties) {
        console.warn('Schema has no properties');
        return html;
    }

    for (const [key, def] of Object.entries(schema.properties)) {
        const fullKey = prefix ? `${prefix}.${key}` : key;
        const value = getValue(data, fullKey);
        console.log(`Field ${fullKey}:`, { definition: def, value: value }); // Debug line

        html += `<div class="mb-4">
            <label class="block text-gray-700 text-sm font-bold mb-2">${def.title || key}</label>`;

        if (def.type === 'object') {
            html += `<div class="pl-4 border-l-2 border-gray-200">
                ${generateFormFields(def, data, fullKey, level)}
            </div>`;
        } else {
            html += generateInputField(def, fullKey, value, level);
        }

        if (def.description) {
            html += `<p class="text-gray-500 text-xs mt-1">${def.description}</p>`;
        }
        html += '</div>';
    }
    return html;
}

function getValue(data, path) {
    console.log('Getting value for path:', { path, data }); // Debug line
    if (!data || !path) return undefined;

    const value = path.split('.').reduce((obj, key) => obj?.[key], data);
    console.log('Found value:', value); // Debug line
    return value;
}

// Modificar la función generateInputField para quitar el onchange
function generateInputField(def, key, value, level) {
    const baseClasses = "w-full p-2 border rounded bg-green-50";

    switch (def.type) {
        case 'string':
            if (def.format === 'directory') {
                return `<div class="flex gap-2">
                    <input type="text" value="${value || ''}" 
                        class="${baseClasses} flex-grow" data-key="${key}">
                    <button type="button" 
                            onclick="browseFieldDirectory(this)" 
                            class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600"
                            data-key="${key}">
                        Buscar...
                    </button>
                </div>`;
            }
            if (def.format === 'file') {
                return `<div class="flex gap-2">
                    <input type="text" value="${value || ''}"
                        class="${baseClasses} flex-grow" data-key="${key}">
                    <button type="button"
                            onclick="browseFieldFile(this)"
                            class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600"
                            data-key="${key}">
                        Buscar...
                    </button>
                    <button type="button"
                            onclick="openFieldFile(this)"
                            class="bg-green-500 text-white px-3 py-1 rounded hover:bg-green-600"
                            data-key="${key}"
                            ${!value ? 'disabled' : ''}>
                        Abrir
                    </button>
                </div>`;
            }
            if (def.enum) {
                return `<select class="${baseClasses}" data-key="${key}">
                    ${def.enum.map(opt => `<option value="${opt}" ${value === opt ? 'selected' : ''}>${opt}</option>`).join('')}
                </select>`;
            }
            return `<input type="text" value="${value || ''}" 
                class="${baseClasses}" data-key="${key}">`;

        case 'number':
            return `<input type="number" value="${value || 0}" 
                class="${baseClasses}" data-key="${key}">`;

        case 'boolean':
            return `<input type="checkbox" ${value ? 'checked' : ''} 
                    class="form-checkbox h-5 w-5 bg-green-50" data-key="${key}">
            `; // <-- Añadir esta comilla invertida
        default:
            return `<input type="text" value="${value || ''}" 
                class="${baseClasses}" data-key="${key}">`;
    }
}

// Agregar nueva función para manejar la búsqueda de directorio
async function browseFieldDirectory(button) {
    const input = button.parentElement.querySelector('input');
    const currentPath = input.value;

    try {
        const response = await fetch(`/api/browse-directories?current_path=${encodeURIComponent(currentPath)}`);
        const result = await response.json();

        if (result.status === 'success') {
            input.value = result.path;
            // Disparar un evento change para actualizar el valor internamente
            const event = new Event('change', { bubbles: true });
            input.dispatchEvent(event);
        }
    } catch (error) {
        console.error('Error browsing directory:', error);
        alert('Error al buscar el directorio');
    }
}

// Agregar nueva función para manejar la búsqueda de un archivo
async function browseFieldFile(button) {
    const input = button.parentElement.querySelector('input');
    const currentPath = input.value;

    try {
        const response = await fetch(`/api/browse-files?current_path=${encodeURIComponent(currentPath)}`);
        const result = await response.json();

        if (result.status === 'success') {
            input.value = result.path;
            // Disparar un evento change para actualizar el valor internamente
            const event = new Event('change', {
                bubbles: true
            });
            input.dispatchEvent(event);

            // Habilitar el botón "Abrir" después de seleccionar un archivo
            const openButton = button.parentElement.querySelector('button[onclick="openFieldFile(this)"]');
            if (openButton) {
                openButton.disabled = false;
            }
        }
    } catch (error) {
        console.error('Error browsing file:', error);
        alert('Error al buscar el archivo');
    }
}

// Agregar función para abrir el archivo seleccionado
async function openFieldFile(button) {
    const input = button.parentElement.querySelector('input');
    const filePath = input.value;

    if (!filePath || filePath.trim() === '') {
        alert('No hay archivo seleccionado para abrir');
        return;
    }

    try {
        const response = await fetch('/api/open-file', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ path: filePath })
        });

        const result = await response.json();
        if (result.status === 'success') {
            console.log('Archivo abierto correctamente');
        } else {
            alert(`Error al abrir el archivo: ${result.message}`);
        }
    } catch (error) {
        console.error('Error opening file:', error);
        alert('Error al abrir el archivo');
    }
}

async function modifySchema(level) {
    try {
        console.log('Loading schema for level:', level); // Debug line
        const response = await fetch(`/api/schema/${level}?group=${currentGroup}`);
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        const schema = await response.json();
        console.log('Loaded schema:', schema); // Debug line

        // Show schema editor modal
        const modal = document.getElementById('schema-editor');
        if (!modal) {
            throw new Error('Schema editor modal not found');
        }
        modal.classList.remove('hidden');

        // Inicializar el esquema si está vacío
        const finalSchema = Object.keys(schema).length === 0 ?
            { type: 'object', properties: {} } : schema;

        // Inicializar editores
        const jsonEditor = document.getElementById('json-editor');
        const visualEditor = document.getElementById('visual-editor');
        const schemaLevel = document.getElementById('schema-level');

        if (!jsonEditor || !visualEditor || !schemaLevel) {
            throw new Error('Required editor elements not found');
        }

        jsonEditor.value = JSON.stringify(finalSchema, null, 2);
        visualEditor.innerHTML = '<div id="schema-fields" class="mb-4"></div>' +
            '<button onclick="addSchemaField()" class="mt-4 bg-green-500 text-white px-4 py-2 rounded">Agregar Campo</button>';
        schemaLevel.value = level;

        // Renderizar editor visual
        renderVisualEditor(finalSchema);

        // Activar pestaña visual por defecto
        switchEditorMode('visual');
    } catch (error) {
        console.error('Error loading schema:', error);
        alert('Error cargando el esquema: ' + error.message);
    }
}

function switchEditorMode(mode) {
    const visualEditor = document.getElementById('visual-editor');
    const jsonEditor = document.getElementById('json-editor');
    const visualTab = document.getElementById('visual-tab');
    const jsonTab = document.getElementById('json-tab');

    if (mode === 'visual') {
        visualEditor.classList.remove('hidden');
        jsonEditor.classList.add('hidden');
        visualTab.classList.add('border-blue-500');
        jsonTab.classList.remove('border-blue-500');

        // Actualizar el editor visual desde JSON
        try {
            const schema = JSON.parse(jsonEditor.value);
            renderVisualEditor(schema);
        } catch (e) {
            console.error('Error parsing JSON:', e);
        }
    } else {
        visualEditor.classList.add('hidden');
        jsonEditor.classList.remove('hidden');
        visualTab.classList.remove('border-blue-500');
        jsonTab.classList.add('border-blue-500');

        // Actualizar el JSON desde el editor visual
        try {
            const schema = updateVisualSchema();
            jsonEditor.value = JSON.stringify(schema, null, 2);
        } catch (e) {
            console.error('Error updating JSON:', e);
        }
    }
}

function renderVisualEditor(schema) {
    const container = document.getElementById('schema-fields');
    container.innerHTML = '';

    Object.entries(schema.properties || {}).forEach(([key, field]) => {
        container.appendChild(createFieldEditor(key, field));
    });
}

function createFieldEditor(key, field) {
    const div = document.createElement('div');
    div.className = 'mb-6 p-4 border rounded schema-field';
    div.innerHTML = `
        <div class="grid grid-cols-2 gap-4">
            <div>
                <label class="block text-sm font-bold mb-2">Nombre del Campo</label>
                <input type="text" value="${key}" 
                       class="w-full p-2 border rounded"
                       onchange="updateVisualSchema()">
            </div>
            <div>
                <label class="block text-sm font-bold mb-2">Tipo</label>
                <select class="w-full p-2 border rounded"
                        onchange="updateFieldType(this)">
                    <option value="string" ${field.type === 'string' && !field.enum && !field.format ? 'selected' : ''}>Texto</option>
                    <option value="directory" ${field.type === 'string' && field.format === 'directory' ? 'selected' : ''}>Directorio</option>
                    <option value="file" ${field.type === 'string' && field.format === 'file' ? 'selected' : ''}>Archivo</option>
                    <option value="number" ${field.type === 'number' ? 'selected' : ''}>Número</option>
                    <option value="boolean" ${field.type === 'boolean' ? 'selected' : ''}>Booleano</option>
                    <option value="enum" ${field.enum ? 'selected' : ''}>Lista de Opciones</option>
                </select>
            </div>
            <div>
                <label class="block text-sm font-bold mb-2">Título</label>
                <input type="text" value="${field.title || ''}" 
                       class="w-full p-2 border rounded"
                       onchange="updateVisualSchema()">
            </div>
            <div>
                <label class="block text-sm font-bold mb-2">Descripción</label>
                <input type="text" value="${field.description || ''}" 
                       class="w-full p-2 border rounded"
                       onchange="updateVisualSchema()">
            </div>
            <div>
                <label class="block text-sm font-bold mb-2">Valor por Defecto</label>
                <input type="text" value="${field.default !== undefined ? field.default : ''}"
                       class="w-full p-2 border rounded"
                       onchange="updateVisualSchema()">
            </div>
        </div>
        ${field.enum ? `
            <div class="enum-container mt-4">
                <label class="block text-sm font-bold mb-2">Opciones (una por línea)</label>
                <textarea class="w-full p-2 border rounded" rows="3"
                         onchange="updateVisualSchema()">${field.enum.join('\n')}</textarea>
            </div>
        ` : ''}
        <button onclick="removeField(this)" 
                class="mt-2 bg-red-500 text-white px-3 py-1 rounded">
            Eliminar Campo
        </button>
    `;
    return div;
}

function updateFieldType(select) {
    const fieldContainer = select.closest('.schema-field');
    const enumContainer = fieldContainer.querySelector('.enum-container');

    if (select.value === 'enum') {
        if (!enumContainer) {
            const div = document.createElement('div');
            div.className = 'enum-container mt-4';
            div.innerHTML = `
                <label class="block text-sm font-bold mb-2">Opciones (una por línea)</label>
                <textarea class="w-full p-2 border rounded" rows="3"
                         onchange="updateVisualSchema()"></textarea>
            `;
            fieldContainer.appendChild(div);
        }
    } else if (enumContainer) {
        enumContainer.remove();
    }
    updateVisualSchema();
}

function removeField(button) {
    const fieldContainer = button.closest('.schema-field');
    fieldContainer.remove();
    updateVisualSchema();
}

function createEnumEditor(enumValues) {
    return `
        <div class="mt-4">
            <label class="block text-sm font-bold mb-2">Opciones (una por línea)</label>
            <textarea class="w-full p-2 border rounded" rows="3"
                     onchange="updateEnumValues(this)">${enumValues.join('\n')}</textarea>
        </div>
    `;
}

function addSchemaField() {
    const container = document.getElementById('schema-fields');
    const newField = createFieldEditor(`campo_${Date.now()}`, {
        type: 'string',
        title: 'Nuevo Campo',
        description: ''
    });
    container.appendChild(newField);
}

// Funciones de actualización del esquema visual
function updateVisualSchema() {
    try {
        const fields = document.getElementById('schema-fields').children;
        const schema = {
            type: 'object',
            properties: {}
        };

        Array.from(fields).forEach(field => {
            const inputs = field.getElementsByTagName('input');
            const select = field.getElementsByTagName('select')[0];
            const key = inputs[0].value;
            const fieldType = select.value; // string, directory, number, boolean, enum
            const title = inputs[1].value;
            const description = inputs[2].value;
            const defaultValueInput = inputs[3]; // El nuevo input de valor por defecto
            const defaultValueString = defaultValueInput.value;

            let propertyDefinition = {
                type: fieldType === 'directory' || fieldType === 'enum' || fieldType === 'file' ? 'string' : fieldType, // El tipo base
                title: title,
                description: description
            };

            // Añadir formato específico si es directorio o archivo
            if (select.value === 'directory') {
                propertyDefinition.format = 'directory';
            } else if (select.value === 'file') {
                propertyDefinition.format = 'file';
            }


            // Añadir enum si es de tipo enum
            if (select.value === 'enum') {
                propertyDefinition.enum = field.querySelector('textarea').value.split('\n').filter(v => v.trim());
            }

            // Procesar y añadir el valor por defecto si se proporcionó
            if (defaultValueString !== null && defaultValueString.trim() !== '') {
                let typedDefaultValue = defaultValueString;
                try {
                    if (propertyDefinition.type === 'number' || propertyDefinition.type === 'integer') {
                        typedDefaultValue = Number(defaultValueString);
                        if (isNaN(typedDefaultValue)) {
                            console.warn(`Valor por defecto inválido para número en campo '${key}': ${defaultValueString}. Se omitirá.`);
                            // No añadir default si no es un número válido
                        } else {
                            // Opcional: truncar si el tipo es integer
                            if (propertyDefinition.type === 'integer' && !Number.isInteger(typedDefaultValue)) {
                                typedDefaultValue = Math.trunc(typedDefaultValue);
                            }
                            propertyDefinition.default = typedDefaultValue;
                        }
                    } else if (propertyDefinition.type === 'boolean') {
                        typedDefaultValue = ['true', '1', 'yes', 'on'].includes(defaultValueString.toLowerCase());
                        propertyDefinition.default = typedDefaultValue;
                    } else { // string, enum, directory
                        propertyDefinition.default = typedDefaultValue; // Ya es string
                    }
                } catch (e) {
                    console.error(`Error procesando valor por defecto para campo '${key}':`, e);
                }
            }
            schema.properties[key] = propertyDefinition;
        });

        const jsonEditor = document.getElementById('json-editor');
        if (jsonEditor) {
            jsonEditor.value = JSON.stringify(schema, null, 2);
        }

        return schema;
    } catch (error) {
        console.error('Error updating schema:', error);
        return null;
    }
}

async function saveSchema() {
    try {
        const level = document.getElementById('schema-level').value;
        let schema;

        // Obtener el esquema según el modo activo
        const visualEditor = document.getElementById('visual-editor');
        const jsonEditor = document.getElementById('json-editor');

        if (!visualEditor.classList.contains('hidden')) {
            schema = updateVisualSchema();
        } else {
            schema = JSON.parse(jsonEditor.value);
        }

        console.log('Saving schema:', schema); // Debug line

        const response = await fetch(`/api/schema/${level}?group=${currentGroup}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(schema)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        // Recargar el formulario
        const configResponse = await fetch(`/api/config/${level}?group=${currentGroup}`);
        const data = await configResponse.json();
        await renderForm(`level${level}-form`, data);

        // Cerrar modal
        document.getElementById('schema-editor').classList.add('hidden');
    } catch (e) {
        console.error('Error saving schema:', e);
        alert('Error guardando esquema: ' + e.message);
    }
}

async function setWorkingDirectory() {
    if (!currentGroup) {
        alert('Por favor, seleccione un grupo de scripts primero');
        return;
    }

    const path = document.getElementById('working-directory').value;
    await updateWorkingDirectory(path);
}

// Modificar initWorkingDirectory para cargar también el historial
async function initWorkingDirectory() {
    if (!currentGroup) return;

    const response = await fetch(`/api/working-directory/${currentGroup}`);
    const result = await response.json();
    if (result.status === 'success' && result.path) {
        await updateWorkingDirectory(result.path);
    }
    await loadDirectoryHistory();
}

async function browseDirectory() {
    console.log('Current group when browsing:', currentGroup); // Debug line
    if (!currentGroup) {
        alert('Por favor, seleccione un grupo de scripts primero');
        return;
    }

    const currentPath = document.getElementById('working-directory').value;
    const response = await fetch(`/api/browse-directories?current_path=${encodeURIComponent(currentPath)}`);
    const result = await response.json();

    if (result.status === 'success') {
        await updateWorkingDirectory(result.path);
    }
}

// Nueva función auxiliar para actualizar el directorio de trabajo
async function updateWorkingDirectory(path) {
    console.log('Updating working directory:', { path, group: currentGroup }); // Debug line

    try {
        const response = await fetch('/api/working-directory', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                path: path,
                group: currentGroup
            })
        });

        const result = await response.json();
        console.log('Update result:', result); // Debug line

        if (result.status === 'success') {
            // Actualizar input y lista de directorios
            document.getElementById('working-directory').value = path;
            await loadDirectoryHistory();

            // Recargar configuración de nivel 3
            const configResponse = await fetch(`/api/config/3?group=${currentGroup}`);
            const data = await configResponse.json();
            await renderForm('level3-form', data);
        } else {
            alert('Error: ' + (result.message || 'No se pudo actualizar el directorio de trabajo'));
        }
    } catch (error) {
        console.error('Error updating working directory:', error);
        alert('Error actualizando el directorio de trabajo: ' + error.message);
    }
}

async function loadDirectoryHistory() {
    try {
        const response = await fetch(`/api/directory-history/${currentGroup}`);
        const history = await response.json();

        const select = document.getElementById('directory-history');
        select.innerHTML = '<option value="">-- Directorios recientes --</option>';

        history.forEach(dir => {
            const option = document.createElement('option');
            option.value = dir;
            option.textContent = dir;
            // Marcar como seleccionado si es el directorio actual
            if (dir === document.getElementById('working-directory').value) {
                option.selected = true;
            }
            select.appendChild(option);
        });
    } catch (error) {
        console.error('Error loading directory history:', error);
    }
}

function loadHistoryDirectory(path) {
    if (path) {
        document.getElementById('working-directory').value = path;
        updateWorkingDirectory(path);  // Cambiado de setWorkingDirectory a updateWorkingDirectory
    }
}

// Función para alternar visibilidad de una sección
function toggleConfig(sectionId) {
    const content = document.getElementById(sectionId);
    const button = document.querySelector(`[onclick="toggleConfig('${sectionId}')"]`);

    if (content.classList.contains('hidden')) {
        content.classList.remove('hidden');
        button.innerText = 'Ocultar Configuración';

        // Recargar la configuración al mostrar
        const level = sectionId.replace('level', '').replace('-content', '');
        const formId = `level${level}-form`;
        console.log(`Reloading config for level ${level}`); // Debug line

        fetch(`/api/config/${level}?group=${currentGroup}`)
            .then(response => response.json())
            .then(data => renderForm(formId, data))
            .catch(error => console.error('Error reloading config:', error));
    } else {
        content.classList.add('hidden');
        button.innerText = 'Mostrar Configuración';
    }
}

async function clearLogs() {
    // Eliminada la confirmación - directamente procede a limpiar
    const response = await fetch('/api/logs', { method: 'DELETE' });
    const result = await response.json();
    if (result.status === 'success') {
        document.getElementById('log-area').innerHTML = '';
        showToast ? showToast('Logs borrados correctamente', 'success') : console.log('Logs cleared');
    } else {
        showToast ? showToast('Error al borrar los logs', 'error') : alert('Error al borrar los logs');
    }
}

async function loadStoredLogs() {
    const response = await fetch('/api/logs');
    const result = await response.json();
    const logArea = document.getElementById('log-area');
    logArea.innerHTML = result.logs;
    logArea.scrollTop = logArea.scrollHeight;
}

// Initialize on page load
async function initializeApp() {
    try {
        // Inicializar WebSocket
        initWebSocket();
        await loadStoredLogs();

        // Configurar grupo actual
        const selectElement = document.getElementById('script-group');
        currentGroup = localStorage.getItem('selectedGroup') || selectElement.value;

        // Actualizar el select con el valor guardado
        if (currentGroup) {
            selectElement.value = currentGroup;
        }

        // Limpiar evento anterior si existe
        selectElement.removeEventListener('change', handleGroupChange);

        // Agregar el nuevo manejador de eventos
        selectElement.addEventListener('change', handleGroupChange);

        // Event listener para el nuevo botón de abrir en explorador
        const openInExplorerButton = document.getElementById('open-in-explorer-btn');
        if (openInExplorerButton) {
            openInExplorerButton.addEventListener('click', openCurrentWorkingDirectoryInExplorer);
        }

        // Cargar datos iniciales
        updateGroupDescription();
        await initWorkingDirectory();
        await loadConfigs();

        // Mostrar level3-content por defecto
        const level3Content = document.getElementById('level3-content');
        if (level3Content) {
            level3Content.classList.remove('hidden');
            const button = document.querySelector(`[onclick="toggleConfig('level3-content')"]`);
            if (button) {
                button.innerText = 'Ocultar Configuración';
            }
        }

    } catch (error) {
        console.error('Error during initialization:', error);
    }
}

// Separar la lógica del cambio de grupo en una función
async function handleGroupChange(e) {
    try {
        currentGroup = e.target.value;
        localStorage.setItem('selectedGroup', currentGroup);
        console.log('Group changed to:', currentGroup);

        // Limpiar formularios existentes
        ['level1-form', 'level2-form', 'level3-form'].forEach(id => {
            const element = document.getElementById(id);
            if (element) element.innerHTML = '';
        });

        // Actualizar la interfaz
        updateGroupDescription();
        await initWorkingDirectory();
        await loadConfigs();

        // Cerrar sidebar en móviles
        if (window.innerWidth < 768) {
            toggleSidebar();
        }
    } catch (error) {
        console.error('Error in handleGroupChange:', error);
    }
}

// Modificar la inicialización para usar la nueva función async
document.addEventListener('DOMContentLoaded', () => {
    initializeApp().catch(console.error);
});

// Función auxiliar para obtener timestamp formateado
function getTimestamp() {
    const now = new Date();
    return now.toLocaleTimeString('es-ES', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
    });
}

// Función para agregar línea al log con timestamp
function addLogLine(message) {
    const logArea = document.getElementById('log-area');

    // Message from WebSocket should already have timestamp.
    // Trim any extra whitespace just in case.
    const cleanMessage = String(message).trim();

    if (cleanMessage) {
        // Append the cleaned message + a newline for display separation.
        logArea.innerHTML += cleanMessage + '\n';
        logArea.scrollTop = logArea.scrollHeight; // Ensure scroll to bottom
        
        // Detectar finalización de scripts
        handleScriptCompletion(cleanMessage);
    }
}

function updateGroupDescription() {
    const select = document.getElementById('script-group');
    const option = select.options[select.selectedIndex];
    const description = option.getAttribute('data-description');
    document.getElementById('group-description').textContent = description;
}

function toggleSidebar() {
    const sidebar = document.querySelector('.sidebar');
    const overlay = document.querySelector('.overlay');
    const schemaEditor = document.getElementById('schema-editor');

    // No cerrar sidebar si el modal está abierto
    if (!schemaEditor.classList.contains('hidden')) {
        return;
    }

    sidebar.classList.toggle('open');
    overlay.classList.toggle('show');
}

async function editGroupDescription() {
    if (!currentGroup) {
        alert('Por favor, seleccione un grupo de scripts primero');
        return;
    }

    try {
        const response = await fetch(`/api/group-description/${currentGroup}`);
        if (!response.ok) throw new Error('Error cargando descripción del grupo');
        const description = await response.json();

        // Show schema editor modal with description data
        const modal = document.getElementById('schema-editor');
        const modalTitle = modal.querySelector('h3');
        const visualEditor = document.getElementById('visual-editor');
        const jsonEditor = document.getElementById('json-editor');
        const tabs = document.getElementById('editor-tabs');

        // Configurar modal para edición de descripción
        modalTitle.textContent = 'Editar Descripción del Grupo';
        tabs.classList.add('hidden');

        // Crear el formulario en el visualEditor
        visualEditor.innerHTML = `
            <form id="group-description-form" class="grid gap-4">
                <div>
                    <label class="block text-sm font-bold mb-2">Nombre del Grupo</label>
                    <input type="text" name="name" class="w-full p-2 border rounded" 
                           value="${description.name || ''}" placeholder="Nombre del grupo">
                </div>
                <div>
                    <label class="block text-sm font-bold mb-2">Descripción</label>
                    <textarea name="description" class="w-full p-2 border rounded" rows="3" 
                             placeholder="Descripción detallada del grupo">${description.description || ''}</textarea>
                </div>
                <div class="grid grid-cols-2 gap-4">
                    <div>
                        <label class="block text-sm font-bold mb-2">Versión</label>
                        <input type="text" name="version" class="w-full p-2 border rounded" 
                               value="${description.version || '1.0'}" placeholder="1.0">
                    </div>
                    <div>
                        <label class="block text-sm font-bold mb-2">Autor</label>
                        <input type="text" name="author" class="w-full p-2 border rounded" 
                               value="${description.author || ''}" placeholder="Nombre del autor">
                    </div>
                </div>
            </form>
        `;
        visualEditor.classList.remove('hidden');
        jsonEditor.classList.add('hidden');

        modal.classList.remove('hidden');

        // Cambiar comportamiento de todos los botones de guardar
        const saveButtons = modal.querySelectorAll('button[onclick="saveSchema()"]');
        saveButtons.forEach(btn => {
            btn.onclick = async () => {
                try {
                    const form = document.getElementById('group-description-form');
                    const formData = new FormData(form);

                    const updatedDescription = {
                        name: formData.get('name') || '',
                        description: formData.get('description') || '',
                        version: formData.get('version') || '1.0',
                        author: formData.get('author') || ''
                    };

                    const saveResponse = await fetch(`/api/group-description/${currentGroup}`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(updatedDescription)
                    });

                    if (!saveResponse.ok) throw new Error('Error guardando descripción');

                    // Restaurar modal a su estado original
                    modalTitle.textContent = 'Editor de Esquema';
                    tabs.classList.remove('hidden');
                    saveButtons.forEach(btn => btn.onclick = saveSchema);
                    modal.classList.add('hidden');

                    // Recargar la página para actualizar la descripción
                    location.reload();
                } catch (e) {
                    alert('Error guardando descripción: ' + e.message);
                }
            };
        });

    } catch (e) {
        alert('Error: ' + e.message);
    }
}

// Agregar función para recolectar datos del formulario
function collectFormData(level) {
    const formContainer = document.getElementById(`level${level}-form`);
    const data = {};

    formContainer.querySelectorAll('input, select').forEach(input => {
        const key = input.getAttribute('data-key');
        if (!key) return;

        let value;
        if (input.type === 'checkbox') {
            value = input.checked;
        } else if (input.type === 'number') {
            value = Number(input.value);
        } else {
            value = input.value;
        }

        // Manejar claves anidadas (por ejemplo: "parent.child")
        const keys = key.split('.');
        let current = data;
        for (let i = 0; i < keys.length - 1; i++) {
            current[keys[i]] = current[keys[i]] || {};
            current = current[keys[i]];
        }
        current[keys[keys.length - 1]] = value;
    });

    return data;
}

// Añade esta función al final de tu archivo static/js/script.js

function shutdownServer() {
    if (confirm("¿Estás seguro de que quieres detener el servidor? La aplicación se cerrará.")) {
        fetch('/_shutdown', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            }
        })
            .then(response => response.json())
            .then(data => {
                if (data.status === 'success') {
                    alert("El servidor se está deteniendo. Puede que necesites cerrar esta pestaña manualmente.");
                    // Opcionalmente, puedes intentar cerrar la ventana/pestaña
                    // window.close(); // Esto puede no funcionar en todos los navegadores por seguridad
                    document.body.innerHTML = '<div class="alert alert-info">El servidor se ha detenido. Cierra esta ventana.</div>';
                } else {
                    alert("Error al intentar detener el servidor: " + data.message);
                }
            })
            .catch(error => {
                // Es normal recibir un error de red aquí porque el servidor se está apagando
                console.warn("Error esperado al detener el servidor (puede que ya se haya detenido):", error);
                alert("Solicitud de detención enviada. El servidor debería detenerse. Cierra esta ventana.");
                document.body.innerHTML = '<div class="alert alert-info">El servidor se está deteniendo. Cierra esta ventana.</div>';
            });
    }
}

// Asegúrate de que las funciones fetchLogs y clearLogs también estén definidas en este archivo si las usas.
// Ejemplo de fetchLogs y clearLogs (si no las tienes ya):

function fetchLogs() {
    fetch('/api/logs')
        .then(response => response.json())
        .then(data => {
            const logOutput = document.getElementById('log-area'); // Corregido ID a log-area
            logOutput.innerHTML = data.logs || 'No hay logs.'; // Usar innerHTML para mantener formato si existe
            logOutput.scrollTop = logOutput.scrollHeight; // Scroll to bottom
        })
        .catch(error => console.error('Error fetching logs:', error));
}

// Necesitarás una función showToast o similar si la usas
function showToast(message, type = 'success') {
    // Implementa tu lógica de Toast aquí
    console.log(`UI (${type}): ${message}`); // Siempre loguea en consola

    if (type === 'error') {
        alert(`Error: ${message}`); // Muestra alerta solo para errores
    }
}

// Llama a fetchLogs al cargar la página si es necesario
// document.addEventListener('DOMContentLoaded', fetchLogs);

// Agregar función para guardar configuración
async function saveConfig(level) {
    const saveButton = document.getElementById(`save-config-${level}`);
    if (!saveButton || saveButton.disabled) return; // Evitar múltiples envíos

    const originalText = saveButton.innerText;
    const originalClasses = 'bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded transition-colors duration-300';

    try {
        saveButton.disabled = true;
        saveButton.className = 'bg-yellow-500 text-white px-4 py-2 rounded cursor-wait transition-colors duration-300';
        saveButton.innerText = 'Guardando...';

        const formData = collectFormData(level);

        const response = await fetch(`/api/config/${level}?group=${currentGroup}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(formData)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const result = await response.json();
        if (result.status === 'success') {
            saveButton.className = 'bg-green-500 text-white px-4 py-2 rounded transition-colors duration-300';
            saveButton.innerText = '¡Guardado con Éxito!';

            setTimeout(() => {
                if (saveButton) {
                    saveButton.className = originalClasses;
                    saveButton.innerText = originalText;
                    saveButton.disabled = false;
                }
            }, 2000);
        } else {
            throw new Error(result.message || 'Error desconocido');
        }
    } catch (error) {
        console.error('Error saving config:', error);
        saveButton.className = 'bg-red-500 text-white px-4 py-2 rounded transition-colors duration-300';
        saveButton.innerText = 'Error al Guardar';

        setTimeout(() => {
            if (saveButton) {
                saveButton.className = originalClasses;
                saveButton.innerText = originalText;
                saveButton.disabled = false;
            }
        }, 2000);
    }
}

async function openGroupInEditor(editorCode, groupSystem, groupId) {
    // groupId is already the currentGroup string from the select
    if (!groupId) {
        alert('Por favor, seleccione un grupo de scripts 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(`${editorName} opened successfully`);
            } else {
                console.error(`Error al abrir ${editorName}:`, result.message);
                alert(`Error al abrir ${editorName}: ${result.message}`);
            }
        }
    } 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}.`);
    }
}

function openMinicondaConsole() {
    fetch('/api/open-miniconda', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        }
    })
        .then(response => response.json())
        .then(data => {
            if (data.status === 'success') {
                showNotification('Miniconda Console abierta correctamente', 'success');
            } else {
                showNotification(`Error al abrir Miniconda Console: ${data.message}`, 'error');
            }
        })
        .catch(error => {
            console.error('Error opening Miniconda Console:', error);
            showNotification('Error al comunicarse con el servidor', 'error');
        });
}

function updateBackendSetup(btnEl) {
    // Mostrar confirmación antes de proceder
    if (!confirm('¿Estás seguro de que quieres actualizar todos los archivos backend_setup.md?\n\nEsto copiará el contenido del archivo principal a todos los archivos backend_setup.md encontrados en subdirectorios .doc.')) {
        return;
    }

    // Mostrar indicador de carga
    const button = btnEl;
    const originalText = button ? button.innerHTML : null;
    if (button) {
        button.innerHTML = '⏳ Actualizando...';
        button.disabled = true;
    }

    fetch('/api/update-backend-setup', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        }
    })
        .then(response => response.json())
        .then(data => {
            if (data.status === 'success') {
                showNotification(`✅ ${data.message}`, 'success');
                if (data.updated_files > 0) {
                    console.log(`Actualizados ${data.updated_files} archivos de ${data.total_files} encontrados`);
                }
            } else {
                showNotification(`❌ Error: ${data.message}`, 'error');
            }
        })
        .catch(error => {
            console.error('Error updating backend setup:', error);
            showNotification('Error al comunicarse con el servidor', 'error');
        })
        .finally(() => {
            // Restaurar el botón
            if (button && originalText !== null) {
                button.innerHTML = originalText;
                button.disabled = false;
            }
        });
}

async function openCurrentWorkingDirectoryInExplorer() {
    const group = currentGroup; // Asumiendo que currentGroup está disponible globalmente
    const wdInput = document.getElementById('working-directory');
    const path = wdInput.value;

    if (!group) {
        showToast("Por favor, selecciona un grupo primero.", "warning"); // O usa alert() si showToast no está definida
        // alert("Por favor, selecciona un grupo primero.");
        return;
    }
    if (!path || path.trim() === "") {
        showToast("El directorio de trabajo no está establecido.", "warning");
        // alert("El directorio de trabajo no está establecido.");
        return;
    }

    try {
        const response = await fetch('/api/open-explorer', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ path: path, group: group })
        });
        const result = await response.json();
        if (result.status === "success") {
            // No es necesario un toast para éxito, la acción es visible
        } else {
            showToast(result.message || "Error al intentar abrir el explorador.", "error");
        }
    } catch (error) {
        console.error("Error de red al abrir en explorador:", error);
        showToast("Error de red al intentar abrir el explorador.", "error");
    }
}

async function openGroupFolder(groupSystem, groupId) {
    if (!groupId) {
        alert('Por favor, seleccione un grupo de scripts primero');
        return;
    }

    try {
        const response = await fetch(`/api/open-group-folder/${groupSystem}/${groupId}`, {
            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');
    }
}

async function copyGroupPath(groupSystem, groupId) {
    if (!groupId) {
        alert('Por favor, seleccione un grupo de scripts primero');
        return;
    }

    try {
        const response = await fetch(`/api/get-group-path/${groupSystem}/${groupId}`);
        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);
                showToast ? showToast('Path copiado al portapapeles', 'success') : alert('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');
                    showToast ? showToast('Path copiado al portapapeles', 'success') : alert('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');
    }
}