<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>🦙 Ollama Model Manager</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            color: #333;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }

        .header {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            padding: 25px;
            margin-bottom: 25px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
            backdrop-filter: blur(10px);
        }

        .header h1 {
            color: #4a5568;
            font-size: 2.5em;
            margin-bottom: 10px;
            text-align: center;
        }

        .header p {
            color: #718096;
            text-align: center;
            font-size: 1.1em;
        }

        .status-bar {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 12px;
            padding: 20px;
            margin-bottom: 25px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 15px;
        }

        .status-indicator {
            display: flex;
            align-items: center;
            gap: 10px;
            font-weight: 600;
        }

        .status-dot {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            animation: pulse 2s infinite;
        }

        .status-dot.online {
            background: #48bb78;
        }

        .status-dot.offline {
            background: #f56565;
            animation: none;
        }

        @keyframes pulse {
            0% {
                opacity: 1;
            }

            50% {
                opacity: 0.5;
            }

            100% {
                opacity: 1;
            }
        }

        .stats {
            display: flex;
            gap: 20px;
            color: #4a5568;
            font-size: 0.9em;
        }

        .shutdown-section {
            margin-left: auto;
        }

        .main-content {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            padding: 25px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
            backdrop-filter: blur(10px);
        }

        .actions-bar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 25px;
            flex-wrap: wrap;
            gap: 15px;
        }

        .download-section {
            display: flex;
            gap: 10px;
            align-items: center;
        }

        .input-group {
            position: relative;
        }

        select {
            padding: 12px 16px;
            border: 2px solid #e2e8f0;
            border-radius: 8px;
            font-size: 1em;
            background: white;
            transition: border-color 0.3s ease;
        }

        select:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }

        input[type="text"] {
            padding: 12px 16px;
            border: 2px solid #e2e8f0;
            border-radius: 8px;
            font-size: 1em;
            width: 300px;
            transition: border-color 0.3s ease;
        }

        input[type="text"]:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }

        .btn {
            padding: 12px 20px;
            border: none;
            border-radius: 8px;
            font-size: 1em;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }

        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
        }

        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }

        .btn-danger {
            background: linear-gradient(135deg, #f56565 0%, #e53e3e 100%);
            color: white;
        }

        .btn-info {
            background: linear-gradient(135deg, #4299e1 0%, #3182ce 100%);
            color: white;
        }

        .btn-secondary {
            background: #e2e8f0;
            color: #4a5568;
        }

        .btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }

        .models-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
            gap: 20px;
        }

        .model-card {
            background: #f7fafc;
            border-radius: 12px;
            padding: 20px;
            border: 2px solid #e2e8f0;
            transition: all 0.3s ease;
        }

        .model-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
            border-color: #667eea;
        }

        .model-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            margin-bottom: 15px;
        }

        .model-name {
            font-size: 1.2em;
            font-weight: 700;
            color: #2d3748;
            word-break: break-word;
        }

        .model-tag {
            background: #667eea;
            color: white;
            padding: 4px 8px;
            border-radius: 6px;
            font-size: 0.8em;
            font-weight: 600;
        }

        .model-info {
            margin-bottom: 15px;
            color: #4a5568;
        }

        .model-info div {
            margin-bottom: 5px;
            font-size: 0.9em;
        }

        .model-size {
            font-weight: 600;
            color: #2d3748;
        }

        .model-actions {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }

        .loading {
            text-align: center;
            padding: 40px;
            color: #718096;
        }

        .spinner {
            display: inline-block;
            width: 40px;
            height: 40px;
            border: 4px solid #e2e8f0;
            border-radius: 50%;
            border-top-color: #667eea;
            animation: spin 1s ease-in-out infinite;
            margin-bottom: 15px;
        }

        @keyframes spin {
            to {
                transform: rotate(360deg);
            }
        }

        .error {
            background: #fed7d7;
            color: #c53030;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
            border-left: 4px solid #f56565;
        }

        .success {
            background: #c6f6d5;
            color: #2f855a;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
            border-left: 4px solid #48bb78;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #718096;
        }

        .empty-state h3 {
            font-size: 1.5em;
            margin-bottom: 15px;
            color: #4a5568;
        }

        .modal {
            display: none;
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            backdrop-filter: blur(5px);
        }

        .modal-content {
            background-color: white;
            margin: 5% auto;
            padding: 30px;
            border-radius: 15px;
            width: 90%;
            max-width: 600px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #e2e8f0;
        }

        .modal-header h2 {
            color: #2d3748;
            margin: 0;
        }

        .close {
            color: #a0aec0;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
            transition: color 0.3s ease;
        }

        .close:hover {
            color: #4a5568;
        }

        .info-item {
            margin-bottom: 15px;
            padding: 10px;
            background: #f7fafc;
            border-radius: 8px;
        }

        .info-label {
            font-weight: 600;
            color: #4a5568;
            margin-bottom: 5px;
        }

        .info-value {
            color: #2d3748;
            word-break: break-word;
        }

        @media (max-width: 768px) {
            .container {
                padding: 15px;
            }

            .models-grid {
                grid-template-columns: 1fr;
            }

            input[type="text"] {
                width: 100%;
            }

            .actions-bar {
                flex-direction: column;
                align-items: stretch;
            }

            .download-section {
                flex-direction: column;
            }

            .status-bar {
                flex-direction: column;
                gap: 15px;
                text-align: center;
            }

            .shutdown-section {
                margin-left: 0;
                align-self: center;
            }

            .stats {
                justify-content: center;
                text-align: center;
            }
        }
    </style>
</head>

<body>
    <div class="container">
        <!-- Header -->
        <div class="header">
            <h1>🦙 Ollama Model Manager</h1>
            <p>Gestiona tus modelos de Ollama de forma sencilla</p>
        </div>

        <!-- Status Bar -->
        <div class="status-bar">
            <div class="status-indicator">
                <div class="status-dot" id="status-dot"></div>
                <span id="status-text">Verificando conexión...</span>
            </div>
            <div class="stats" id="stats">
                <span>📊 Cargando estadísticas...</span>
            </div>
            <div class="shutdown-section">
                <button class="btn btn-danger" id="shutdown-btn" onclick="shutdownApplication()"
                    title="Cerrar aplicación">
                    🔴 Cerrar
                </button>
            </div>
        </div>

        <!-- Main Content -->
        <div class="main-content">
            <!-- Actions Bar -->
            <div class="actions-bar">
                <h2>Modelos Instalados</h2>
                <div class="download-section">
                    <div class="input-group">
                        <input type="text" id="model-name-input" placeholder="Nombre del modelo (ej: llama3.2, mistral)"
                            autocomplete="off">
                    </div>
                    <button class="btn btn-primary" id="download-btn" onclick="downloadModel()">
                        📥 Descargar
                    </button>
                    <button class="btn btn-secondary" onclick="refreshModels()">
                        🔄 Actualizar
                    </button>
                    <div class="input-group">
                        <label for="sort-select"
                            style="margin-left:10px; margin-right:6px; color:#4a5568; font-weight:600;">Ordenar
                            por:</label>
                        <select id="sort-select">
                            <option value="modified_desc">Última modificación (recientes primero)</option>
                            <option value="modified_asc">Última modificación (antiguos primero)</option>
                            <option value="size_desc">Tamaño (grandes primero)</option>
                            <option value="size_asc">Tamaño (pequeños primero)</option>
                            <option value="name_asc">Nombre (A-Z)</option>
                        </select>
                    </div>
                </div>
            </div>

            <!-- Messages -->
            <div id="messages"></div>

            <!-- Models Grid -->
            <div id="models-container">
                <div class="loading">
                    <div class="spinner"></div>
                    <div>Cargando modelos...</div>
                </div>
            </div>
        </div>
    </div>

    <!-- Modal para información del modelo -->
    <div id="info-modal" class="modal">
        <div class="modal-content">
            <div class="modal-header">
                <h2>📋 Información del Modelo</h2>
                <span class="close" onclick="closeInfoModal()">&times;</span>
            </div>
            <div id="info-modal-body">
                <div class="loading">
                    <div class="spinner"></div>
                    <div>Cargando información...</div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // Estado global de la aplicación
        let currentModels = [];
        let isLoading = false;
        let currentSort = 'modified_desc';

        // Inicializar aplicación
        document.addEventListener('DOMContentLoaded', function () {
            checkOllamaStatus();
            loadModels();

            // Configurar entrada de texto para descargar modelos
            document.getElementById('model-name-input').addEventListener('keypress', function (e) {
                if (e.key === 'Enter') {
                    downloadModel();
                }
            });

            // Configurar selector de orden
            const sortSelect = document.getElementById('sort-select');
            if (sortSelect) {
                sortSelect.value = currentSort;
                sortSelect.addEventListener('change', function () {
                    currentSort = this.value;
                    applySortAndRender();
                });
            }
        });

        // Verificar estado de Ollama
        async function checkOllamaStatus() {
            try {
                const response = await fetch('/api/status');
                const data = await response.json();

                const statusDot = document.getElementById('status-dot');
                const statusText = document.getElementById('status-text');

                if (data.ollama_running) {
                    statusDot.className = 'status-dot online';
                    statusText.textContent = '🟢 Ollama conectado';
                } else {
                    statusDot.className = 'status-dot offline';
                    statusText.textContent = '🔴 Ollama desconectado';
                }
            } catch (error) {
                const statusDot = document.getElementById('status-dot');
                const statusText = document.getElementById('status-text');
                statusDot.className = 'status-dot offline';
                statusText.textContent = '❌ Error de conexión';
            }
        }

        // Cargar modelos
        async function loadModels() {
            if (isLoading) return;

            isLoading = true;
            const container = document.getElementById('models-container');

            // Mostrar spinner de carga
            container.innerHTML = `
                <div class="loading">
                    <div class="spinner"></div>
                    <div>Cargando modelos...</div>
                </div>
            `;

            try {
                const response = await fetch('/api/models');
                const data = await response.json();

                if (data.status === 'success') {
                    currentModels = data.models || [];
                    updateStats(data);
                    applySortAndRender();
                } else {
                    showError(`Error al cargar modelos: ${data.message}`);
                    container.innerHTML = `
                        <div class="error">
                            ❌ Error al cargar modelos: ${data.message}
                        </div>
                    `;
                }
            } catch (error) {
                showError(`Error de conexión: ${error.message}`);
                container.innerHTML = `
                    <div class="error">
                        ❌ Error de conexión: ${error.message}
                    </div>
                `;
            } finally {
                isLoading = false;
            }
        }

        // Aplicar orden y renderizar
        function applySortAndRender() {
            const sorted = [...currentModels];
            const getSize = (m) => typeof m.size === 'number' ? m.size : (parseInt(m.size, 10) || 0);
            const getModifiedTs = (m) => m.modified_at ? (Date.parse(m.modified_at) || 0) : 0;

            switch (currentSort) {
                case 'size_desc':
                    sorted.sort((a, b) => getSize(b) - getSize(a));
                    break;
                case 'size_asc':
                    sorted.sort((a, b) => getSize(a) - getSize(b));
                    break;
                case 'modified_asc':
                    sorted.sort((a, b) => getModifiedTs(a) - getModifiedTs(b));
                    break;
                case 'name_asc':
                    sorted.sort((a, b) => (a.name || '').localeCompare(b.name || ''));
                    break;
                case 'modified_desc':
                default:
                    sorted.sort((a, b) => getModifiedTs(b) - getModifiedTs(a));
                    break;
            }

            renderModels(sorted);
        }

        // Actualizar estadísticas
        function updateStats(data) {
            const statsElement = document.getElementById('stats');
            statsElement.innerHTML = `
                <span>📦 ${data.total_models} modelos</span>
                <span>💾 ${data.total_size_human}</span>
            `;
        }

        // Renderizar modelos
        function renderModels(models) {
            const container = document.getElementById('models-container');

            if (models.length === 0) {
                container.innerHTML = `
                    <div class="empty-state">
                        <h3>🦙 No hay modelos instalados</h3>
                        <p>Descarga tu primer modelo usando el campo de arriba</p>
                        <p><strong>Modelos populares:</strong> llama3.2, mistral, codellama, phi3</p>
                    </div>
                `;
                return;
            }

            const modelsHTML = models.map(model => {
                const sizeFormatted = formatBytes(model.size || 0);
                const modifiedDate = model.modified_at ?
                    new Date(model.modified_at).toLocaleDateString('es-ES', {
                        year: 'numeric',
                        month: 'short',
                        day: 'numeric'
                    }) : 'N/A';

                return `
                    <div class="model-card">
                        <div class="model-header">
                            <div class="model-name">${model.name}</div>
                            <div class="model-tag">LLM</div>
                        </div>
                        <div class="model-info">
                            <div class="model-size">📦 Tamaño: ${sizeFormatted}</div>
                            <div>📅 Modificado: ${modifiedDate}</div>
                            <div>🏷️ Digest: ${(model.digest || 'N/A').substring(0, 12)}...</div>
                        </div>
                        <div class="model-actions">
                            <button class="btn btn-info" onclick="showModelInfo('${model.name}')">
                                ℹ️ Info
                            </button>
                            <button class="btn btn-danger" onclick="deleteModel('${model.name}')">
                                🗑️ Eliminar
                            </button>
                        </div>
                    </div>
                `;
            }).join('');

            container.innerHTML = `<div class="models-grid">${modelsHTML}</div>`;
        }

        // Descargar modelo
        async function downloadModel() {
            const input = document.getElementById('model-name-input');
            const modelName = input.value.trim();

            if (!modelName) {
                showError('Por favor, introduce el nombre del modelo');
                return;
            }

            const downloadBtn = document.getElementById('download-btn');
            downloadBtn.disabled = true;
            downloadBtn.innerHTML = '⏳ Descargando...';

            try {
                const response = await fetch('/api/models/pull', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({ name: modelName })
                });

                const data = await response.json();

                if (data.status === 'success') {
                    showSuccess(`✅ Descarga de "${modelName}" iniciada. Puede tardar varios minutos...`);
                    input.value = '';

                    // Recargar modelos después de unos segundos
                    setTimeout(() => {
                        loadModels();
                    }, 3000);
                } else {
                    showError(`❌ Error al descargar: ${data.message}`);
                }
            } catch (error) {
                showError(`❌ Error de conexión: ${error.message}`);
            } finally {
                downloadBtn.disabled = false;
                downloadBtn.innerHTML = '📥 Descargar';
            }
        }

        // Eliminar modelo
        async function deleteModel(modelName) {
            if (!confirm(`¿Estás seguro de que quieres eliminar el modelo "${modelName}"?`)) {
                return;
            }

            try {
                const response = await fetch(`/api/models/${encodeURIComponent(modelName)}`, {
                    method: 'DELETE'
                });

                const data = await response.json();

                if (data.status === 'success') {
                    showSuccess(`✅ Modelo "${modelName}" eliminado correctamente`);
                    loadModels();
                } else {
                    showError(`❌ Error al eliminar: ${data.message}`);
                }
            } catch (error) {
                showError(`❌ Error de conexión: ${error.message}`);
            }
        }

        // Mostrar información del modelo
        async function showModelInfo(modelName) {
            const modal = document.getElementById('info-modal');
            const modalBody = document.getElementById('info-modal-body');

            modal.style.display = 'block';
            modalBody.innerHTML = `
                <div class="loading">
                    <div class="spinner"></div>
                    <div>Cargando información...</div>
                </div>
            `;

            try {
                const response = await fetch(`/api/models/${encodeURIComponent(modelName)}/info`);
                const data = await response.json();

                if (data.status === 'success') {
                    const info = data.info;
                    modalBody.innerHTML = `
                        <div class="info-item">
                            <div class="info-label">Nombre del Modelo</div>
                            <div class="info-value">${modelName}</div>
                        </div>
                        ${info.license ? `
                        <div class="info-item">
                            <div class="info-label">Licencia</div>
                            <div class="info-value">${info.license}</div>
                        </div>
                        ` : ''}
                        ${info.modelfile ? `
                        <div class="info-item">
                            <div class="info-label">Modelfile</div>
                            <div class="info-value"><pre style="white-space: pre-wrap; font-size: 0.9em;">${info.modelfile}</pre></div>
                        </div>
                        ` : ''}
                        ${info.parameters ? `
                        <div class="info-item">
                            <div class="info-label">Parámetros</div>
                            <div class="info-value"><pre style="white-space: pre-wrap; font-size: 0.9em;">${info.parameters}</pre></div>
                        </div>
                        ` : ''}
                        ${info.template ? `
                        <div class="info-item">
                            <div class="info-label">Template</div>
                            <div class="info-value"><pre style="white-space: pre-wrap; font-size: 0.9em;">${info.template}</pre></div>
                        </div>
                        ` : ''}
                    `;
                } else {
                    modalBody.innerHTML = `
                        <div class="error">
                            ❌ Error al cargar información: ${data.message}
                        </div>
                    `;
                }
            } catch (error) {
                modalBody.innerHTML = `
                    <div class="error">
                        ❌ Error de conexión: ${error.message}
                    </div>
                `;
            }
        }

        // Cerrar modal de información
        function closeInfoModal() {
            document.getElementById('info-modal').style.display = 'none';
        }

        // Cerrar modal al hacer clic fuera de él
        window.onclick = function (event) {
            const modal = document.getElementById('info-modal');
            if (event.target === modal) {
                modal.style.display = 'none';
            }
        }

        // Actualizar modelos
        function refreshModels() {
            checkOllamaStatus();
            loadModels();
        }

        // Mostrar mensaje de error
        function showError(message) {
            showMessage(message, 'error');
        }

        // Mostrar mensaje de éxito
        function showSuccess(message) {
            showMessage(message, 'success');
        }

        // Mostrar mensaje genérico
        function showMessage(message, type) {
            const messagesContainer = document.getElementById('messages');
            const messageDiv = document.createElement('div');
            messageDiv.className = type;
            messageDiv.textContent = message;

            messagesContainer.appendChild(messageDiv);

            // Remover mensaje después de 5 segundos
            setTimeout(() => {
                if (messageDiv.parentNode) {
                    messageDiv.parentNode.removeChild(messageDiv);
                }
            }, 5000);
        }

        // Formatear bytes
        function formatBytes(bytes) {
            if (bytes === 0) return '0 B';

            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));

            return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
        }

        // Cerrar aplicación
        async function shutdownApplication() {
            if (!confirm('¿Estás seguro de que quieres cerrar la aplicación?')) {
                return;
            }

            const shutdownBtn = document.getElementById('shutdown-btn');
            shutdownBtn.disabled = true;
            shutdownBtn.innerHTML = '⏳ Cerrando...';

            try {
                // Mostrar mensaje de cierre
                showSuccess('🛑 Cerrando Ollama Model Manager...');

                // Esperar un momento para que se vea el mensaje
                await new Promise(resolve => setTimeout(resolve, 1000));

                // Enviar solicitud de cierre al servidor
                const response = await fetch('/_shutdown', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    }
                });

                if (response.ok) {
                    // Intentar cerrar la pestaña/ventana del navegador
                    try {
                        window.close();
                    } catch (e) {
                        // Si no se puede cerrar, mostrar mensaje
                        document.body.innerHTML = `
                            <div style="
                                display: flex; 
                                flex-direction: column; 
                                justify-content: center; 
                                align-items: center; 
                                height: 100vh; 
                                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                                color: white;
                                font-family: 'Segoe UI', sans-serif;
                                text-align: center;
                                padding: 20px;
                            ">
                                <h1 style="font-size: 3em; margin-bottom: 20px;">🦙</h1>
                                <h2 style="margin-bottom: 20px;">Ollama Model Manager Cerrado</h2>
                                <p style="font-size: 1.2em; margin-bottom: 30px;">
                                    La aplicación se ha cerrado correctamente.
                                </p>
                                <p style="opacity: 0.8;">
                                    Puedes cerrar esta pestaña manualmente.
                                </p>
                            </div>
                        `;
                    }
                } else {
                    throw new Error('Error en la respuesta del servidor');
                }
            } catch (error) {
                console.error('Error cerrando aplicación:', error);
                showError('❌ Error al cerrar la aplicación');

                // Restaurar botón
                shutdownBtn.disabled = false;
                shutdownBtn.innerHTML = '🔴 Cerrar';
            }
        }
    </script>
</body>

</html>