<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <title>Admin Dashboard - {{ html_title }}</title>

    <!-- Loading overlay to prevent FOUC - MUST be first -->
    {% include 'includes/loading_overlay.html' %}

    <link rel="icon" href="/tool/speakr/static/img/favicon.ico" type="image/svg+xml">
        <!-- All dependencies bundled locally for offline support -->
<script src="/tool/speakr/static/vendor/js/tailwind.min.js"></script>
        <!-- All dependencies bundled locally for offline support -->
<script src="/tool/speakr/static/vendor/js/vue.global.js"></script>
        <!-- All dependencies bundled locally for offline support -->
<link rel="stylesheet" href="/tool/speakr/static/vendor/css/fontawesome.min.css">
    <link rel="stylesheet" href="/tool/speakr/static/css/styles.css">
    <script src="/tool/speakr/static/js/i18n.js"></script>
    <script src="/tool/speakr/static/js/loading.js"></script>
    <style>
        /* Hide Vue content until compiled */
        [v-cloak] {
            display: none !important;
        }

        /* Hide scrollbar for tabs */
        .scrollbar-hide {
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .scrollbar-hide::-webkit-scrollbar {
            display: none;
        }
    </style>
    <script>
        // Initialize i18n
        let t = (key) => key; // Default fallback
        
        async function initializeI18n() {
            const userLanguage = "{{ user_language }}";
            
            // Initialize the global i18n instance
            if (window.i18n) {
                await window.i18n.init(userLanguage);
                
                // Create a shorthand translation function
                t = (key, params) => window.i18n.t(key, params);
                
                // Update all elements with data-i18n attribute
                document.querySelectorAll('[data-i18n]').forEach(el => {
                    const key = el.getAttribute('data-i18n');
                    el.textContent = t(key);
                });
                
                // Update all elements with data-i18n-placeholder attribute
                document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
                    const key = el.getAttribute('data-i18n-placeholder');
                    el.placeholder = t(key);
                });
            }
        }
        
        // Function to apply the theme based on localStorage
        function applyTheme() {
            // Guard against early execution
            if (!document.documentElement) return;

            // Apply dark mode
            const savedMode = localStorage.getItem('darkMode');
            const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
            if (savedMode === 'true' || (savedMode === null && prefersDark)) {
                document.documentElement.classList.add('dark');
            } else {
                document.documentElement.classList.remove('dark');
            }

            // Apply color scheme
            const savedScheme = localStorage.getItem('colorScheme') || 'blue';
            const isDark = document.documentElement.classList.contains('dark');
            const themePrefix = isDark ? 'theme-dark-' : 'theme-light-';
            
            // Remove all other theme classes
            const themeClasses = ['blue', 'emerald', 'purple', 'rose', 'amber', 'teal'];
            themeClasses.forEach(theme => {
                document.documentElement.classList.remove(`theme-light-${theme}`);
                document.documentElement.classList.remove(`theme-dark-${theme}`);
            });

            // Add the correct theme class
            if (savedScheme !== 'blue') {
                 document.documentElement.classList.add(themePrefix + savedScheme);
            }
        }
        applyTheme();
    </script>
</head>
<body class="bg-[var(--bg-primary)] text-[var(--text-primary)]">
    <div id="app" v-cloak class="container mx-auto px-4 sm:px-6 lg:px-8 py-6 flex flex-col min-h-screen">
        <header class="flex justify-between items-center mb-6 pb-4 border-b border-[var(--border-primary)]">
            <h1 class="text-3xl font-bold text-[var(--text-primary)]">
                <a href="/tool/speakr" class="flex items-center">
                    <img src="/tool/speakr/static/img/icon-192x192.png" alt="{{ html_title }} Logo" class="h-9 w-9 mr-2">
                    {{ html_title }}
                </a>
            </h1>
            <div class="flex items-center space-x-2">
                <button @click="toggleDarkMode" class="p-2 rounded-full text-[var(--text-muted)] hover:bg-[var(--bg-tertiary)] dark:text-gray-400 dark:hover:bg-gray-700 transition-colors duration-200" :title="isDarkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'">
                    <i :class="isDarkMode ? 'fas fa-sun' : 'fas fa-moon'"></i>
                </button>
                <div class="relative">
                    <button @click="isUserMenuOpen = !isUserMenuOpen" class="flex items-center px-3 py-2 border border-[var(--border-secondary)] rounded-lg text-[var(--text-secondary)] hover:text-[var(--text-accent)] focus:outline-none">
                        <i class="fas fa-user-shield mr-2"></i>
                        <span>{{ current_user.username }}</span>
                        <i class="fas fa-chevron-down ml-2"></i>
                    </button>
                    <div v-if="isUserMenuOpen" class="absolute right-0 mt-2 w-48 bg-[var(--bg-secondary)] border border-[var(--border-primary)] rounded-lg shadow-lg z-10">
                        <a href="/tool/speakr" class="block px-4 py-2 text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-accent)]">
                            <i class="fas fa-home mr-2"></i> ${t('nav.home')}
                        </a>
                        <a href="/tool/speakr/account" class="block px-4 py-2 text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-accent)]">
                            <i class="fas fa-user mr-2"></i> ${t('nav.account')}
                        </a>
                        <a href="/tool/speakr/admin" class="block px-4 py-2 text-[var(--text-accent)] bg-[var(--bg-accent)]">
                            <i class="fas fa-user-shield mr-2"></i> ${t('nav.admin')}
                        </a>
                        <a href="/tool/speakr/logout" class="block px-4 py-2 text-[var(--text-secondary)] hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-danger)]">
                            <i class="fas fa-sign-out-alt mr-2"></i> ${t('nav.signOut')}
                        </a>
                    </div>
                </div>
            </div>
        </header>

        <main class="flex-grow">
            <div class="bg-[var(--bg-secondary)] p-4 sm:p-6 lg:p-8 rounded-xl shadow-lg border border-[var(--border-primary)]">
                <h2 class="text-2xl font-semibold text-[var(--text-primary)] mb-6">管理仪表盘</h2>
                
                {% with messages = get_flashed_messages(with_categories=true) %}
                    {% if messages %}
                        {% for category, message in messages %}
                            <div class="mb-4 p-3 rounded-lg {% if category == 'success' %}bg-[var(--bg-success-light)] text-[var(--text-success-strong)]{% elif category == 'danger' %}bg-[var(--bg-danger-light)] text-[var(--text-danger-strong)]{% else %}bg-[var(--bg-info-light)] text-[var(--text-info-strong)]{% endif %}">
                                {{ message }}
                            </div>
                        {% endfor %}
                    {% endif %}
                {% endwith %}
                
                <!-- Tabs -->
                <div class="border-b border-[var(--border-primary)] mb-6">
                    <div class="relative">
                        <!-- Scroll gradient indicators -->
                        <div class="absolute left-0 top-0 bottom-0 w-12 bg-gradient-to-r from-[var(--bg-secondary)] to-transparent z-[1] pointer-events-none opacity-0 transition-opacity duration-200 flex items-center justify-start" id="admin-left-scroll-indicator">
                            <i class="fas fa-chevron-left text-[var(--text-muted)] ml-1"></i>
                        </div>
                        <div class="absolute right-0 top-0 bottom-0 w-12 bg-gradient-to-l from-[var(--bg-secondary)] to-transparent z-[1] pointer-events-none opacity-100 transition-opacity duration-200 flex items-center justify-end" id="admin-right-scroll-indicator">
                            <i class="fas fa-chevron-right text-[var(--text-muted)] mr-1"></i>
                        </div>
                        <nav class="tab-nav px-1 sm:px-4 lg:px-6 pt-3 sm:pt-4 lg:pt-6 pb-4 sm:pb-6 -mb-px overflow-x-auto scrollbar-hide" aria-label="Tabs" id="admin-tabs-container">
                            <div class="inline-flex gap-1 sm:gap-2">
                                <button @click="activeTab = 'users'"
                                        :class="activeTab === 'users' ? 'border-[var(--border-accent)] text-[var(--text-accent)]' : 'border-transparent text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'"
                                        class="inline-flex items-center whitespace-nowrap py-1 px-1.5 sm:py-3 sm:px-3 border-b-2 font-medium text-xs sm:text-sm rounded-t-md sm:rounded-t-lg hover:bg-[var(--bg-tertiary)]">
                                    <i class="fas fa-users mr-0.5 sm:mr-2 text-xs sm:text-sm"></i><span>${t('adminDashboard.userManagement')}</span>
                                </button>
                                <button @click="activeTab = 'stats'"
                                        :class="activeTab === 'stats' ? 'border-[var(--border-accent)] text-[var(--text-accent)]' : 'border-transparent text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'"
                                        class="inline-flex items-center whitespace-nowrap py-1 px-1.5 sm:py-3 sm:px-3 border-b-2 font-medium text-xs sm:text-sm rounded-t-md sm:rounded-t-lg hover:bg-[var(--bg-tertiary)]">
                                    <i class="fas fa-chart-bar mr-0.5 sm:mr-2 text-xs sm:text-sm"></i><span>${t('adminDashboard.systemStatistics')}</span>
                                </button>
                                <button @click="activeTab = 'settings'"
                                        :class="activeTab === 'settings' ? 'border-[var(--border-accent)] text-[var(--text-accent)]' : 'border-transparent text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'"
                                        class="inline-flex items-center whitespace-nowrap py-1 px-1.5 sm:py-3 sm:px-3 border-b-2 font-medium text-xs sm:text-sm rounded-t-md sm:rounded-t-lg hover:bg-[var(--bg-tertiary)]">
                                    <i class="fas fa-cogs mr-0.5 sm:mr-2 text-xs sm:text-sm"></i><span>${t('adminDashboard.systemSettings')}</span>
                                </button>
                                <button @click="activeTab = 'prompts'"
                                        :class="activeTab === 'prompts' ? 'border-[var(--border-accent)] text-[var(--text-accent)]' : 'border-transparent text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'"
                                        class="inline-flex items-center whitespace-nowrap py-1 px-1.5 sm:py-3 sm:px-3 border-b-2 font-medium text-xs sm:text-sm rounded-t-md sm:rounded-t-lg hover:bg-[var(--bg-tertiary)]">
                                    <i class="fas fa-file-alt mr-0.5 sm:mr-2 text-xs sm:text-sm"></i><span>${t('adminDashboard.defaultPrompts')}</span>
                                </button>
                                <button @click="activeTab = 'vectorstore'"
                                        :class="activeTab === 'vectorstore' ? 'border-[var(--border-accent)] text-[var(--text-accent)]' : 'border-transparent text-[var(--text-muted)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'"
                                        class="inline-flex items-center whitespace-nowrap py-1 px-1.5 sm:py-3 sm:px-3 border-b-2 font-medium text-xs sm:text-sm rounded-t-md sm:rounded-t-lg hover:bg-[var(--bg-tertiary)]"
                                        v-if="inquireModeEnabled">
                                    <i class="fas fa-database mr-0.5 sm:mr-2 text-xs sm:text-sm"></i><span>${t('adminDashboard.vectorStore')}</span>
                                </button>
                            </div>
                        </nav>
                    </div>
                </div>
                
                <!-- User Management Tab -->
                <div v-show="activeTab === 'users'">
                    <div class="flex justify-between items-center mb-4">
                        <h3 class="text-lg font-medium text-[var(--text-secondary)]">${t('adminDashboard.userManagement')}</h3>
                        <button @click="showAddUserModal = true" class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-lg shadow hover:bg-[var(--bg-button-hover)] focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] focus:ring-offset-2 transition duration-150 ease-in-out">
                            <i class="fas fa-user-plus mr-2"></i> ${t('adminDashboard.addUser')}
                        </button>
                    </div>
                    
                    <!-- Search and Filter -->
                    <div class="mb-4 flex">
                        <div class="relative flex-grow">
                            <input type="text" v-model="userSearchQuery" :placeholder="t('adminDashboard.searchUsers')" class="w-full px-4 py-2 border border-[var(--border-secondary)] rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                            <button v-if="userSearchQuery" @click="userSearchQuery = ''" class="absolute right-3 top-2.5 text-[var(--text-muted)] hover:text-[var(--text-secondary)]">
                                <i class="fas fa-times"></i>
                            </button>
                        </div>
                    </div>
                    
                    <!-- Users Table -->
                    <div class="overflow-x-auto">
                        <table class="min-w-full divide-y divide-[var(--border-primary)]">
                            <thead class="bg-[var(--bg-tertiary)]">
                                <tr>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.id')}</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.username')}</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.email')}</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.admin')}</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.recordings')}</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.storageUsed')}</th>
                                    <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-[var(--text-muted)] uppercase tracking-wider">${t('adminDashboard.actions')}</th>
                                </tr>
                            </thead>
                            <tbody class="bg-[var(--bg-secondary)] divide-y divide-[var(--border-primary)]">
                                <tr v-for="user in filteredUsers" :key="user.id" class="hover:bg-[var(--bg-tertiary)]">
                                    <td class="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-secondary)]">${ user.id }</td>
                                    <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--text-primary)]">${ user.username }</td>
                                    <td class="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-secondary)]">${ user.email }</td>
                                    <td class="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-secondary)]">
                                        <span v-if="user.is_admin" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-[var(--bg-success-light)] text-[var(--text-success-strong)]">Yes</span>
                                        <span v-else class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-[var(--bg-pending-light)] text-[var(--text-pending-strong)]">No</span>
                                    </td>
                                    <td class="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-secondary)]">${ user.recordings_count }</td>
                                    <td class="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-secondary)]">${ formatFileSize(user.storage_used) }</td>
                                    <td class="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-secondary)]">
                                        <div class="flex space-x-2">
                                            <button @click="editUser(user)" class="text-[var(--text-accent)] hover:text-[var(--text-accent-hover)]" :title="t('buttons.editUser')">
                                                <i class="fas fa-edit"></i>
                                            </button>
                                            <button @click="toggleAdminStatus(user)" :class="user.is_admin ? 'text-[var(--text-warn-strong)]' : 'text-[var(--text-info-strong)]'" :title="user.is_admin ? 'Remove Admin' : 'Make Admin'">
                                                <i class="fas" :class="user.is_admin ? 'fa-user-minus' : 'fa-user-shield'"></i>
                                            </button>
                                            <button @click="confirmDeleteUser(user)" class="text-[var(--text-danger)] hover:text-[var(--text-danger-hover)]" :title="t('buttons.deleteUser')">
                                                <i class="fas fa-trash"></i>
                                            </button>
                                        </div>
                                    </td>
                                </tr>
                                <tr v-if="filteredUsers.length === 0">
                                    <td colspan="7" class="px-6 py-4 text-center text-sm text-[var(--text-muted)]">
                                        <div v-if="isLoadingUsers">
                                            <i class="fas fa-spinner fa-spin mr-2"></i> Loading users...
                                        </div>
                                        <div v-else>
                                            No users found.
                                        </div>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                
                <!-- System Statistics Tab -->
                <div v-show="activeTab === 'stats'">
                    <h3 class="text-lg font-medium text-[var(--text-secondary)] mb-4">${t('adminDashboard.systemStatistics')}</h3>
                    
                    <!-- Summary Cards -->
                    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
                        <div class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center">
                                <div class="p-3 rounded-full bg-[var(--bg-info-light)] text-[var(--text-info-strong)]">
                                    <i class="fas fa-users text-xl"></i>
                                </div>
                                <div class="ml-4">
                                    <p class="text-sm font-medium text-[var(--text-muted)]">${t('adminDashboard.totalUsers')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-primary)]">${ stats.total_users }</p>
                                </div>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center">
                                <div class="p-3 rounded-full bg-[var(--bg-success-light)] text-[var(--text-success-strong)]">
                                    <i class="fas fa-file-audio text-xl"></i>
                                </div>
                                <div class="ml-4">
                                    <p class="text-sm font-medium text-[var(--text-muted)]">${t('adminDashboard.totalRecordings')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-primary)]">${ stats.total_recordings }</p>
                                </div>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center">
                                <div class="p-3 rounded-full bg-[var(--bg-warn-light)] text-[var(--text-warn-strong)]">
                                    <i class="fas fa-database text-xl"></i>
                                </div>
                                <div class="ml-4">
                                    <p class="text-sm font-medium text-[var(--text-muted)]">${t('adminDashboard.totalStorage')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-primary)]">${ formatFileSize(stats.total_storage) }</p>
                                </div>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center">
                                <div class="p-3 rounded-full bg-[var(--bg-accent)] text-[var(--text-accent)]">
                                    <i class="fas fa-comments text-xl"></i>
                                </div>
                                <div class="ml-4">
                                    <p class="text-sm font-medium text-[var(--text-muted)]">${t('adminDashboard.totalQueries')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-primary)]">${ stats.total_queries }</p>
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    <!-- Status Distribution -->
                    <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
                        <div class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <h4 class="text-md font-medium text-[var(--text-secondary)] mb-3">${t('adminDashboard.recordingStatusDistribution')}</h4>
                            <div class="grid grid-cols-2 gap-4">
                                <div class="text-center p-3 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] shadow-sm">
                                    <span class="block text-2xl font-bold text-[var(--text-success-strong)]">${ stats.completed_recordings }</span>
                                    <span class="block text-sm text-[var(--text-muted)]">${t('adminDashboard.completedRecordings')}</span>
                                </div>
                                <div class="text-center p-3 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] shadow-sm">
                                    <span class="block text-2xl font-bold text-[var(--text-warn-strong)]">${ stats.processing_recordings }</span>
                                    <span class="block text-sm text-[var(--text-muted)]">${t('adminDashboard.processingRecordings')}</span>
                                </div>
                                <div class="text-center p-3 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] shadow-sm">
                                    <span class="block text-2xl font-bold text-[var(--text-pending-strong)]">${ stats.pending_recordings }</span>
                                    <span class="block text-sm text-[var(--text-muted)]">${t('adminDashboard.pendingRecordings')}</span>
                                </div>
                                <div class="text-center p-3 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)] shadow-sm">
                                    <span class="block text-2xl font-bold text-[var(--text-danger-strong)]">${ stats.failed_recordings }</span>
                                    <span class="block text-sm text-[var(--text-muted)]">${t('adminDashboard.failedRecordings')}</span>
                                </div>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <h4 class="text-md font-medium text-[var(--text-secondary)] mb-3">${t('adminDashboard.topUsersByStorage')}</h4>
                            <div class="space-y-3">
                                <div v-for="user in stats.top_users" :key="user.id" class="flex justify-between items-center p-2 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)]">
                                    <div class="flex items-center">
                                        <i class="fas fa-user text-[var(--text-accent)] mr-2"></i>
                                        <span class="text-sm font-medium text-[var(--text-primary)]">${ user.username }</span>
                                    </div>
                                    <div class="text-sm text-[var(--text-secondary)]">
                                        <span class="font-medium">${ formatFileSize(user.storage_used) }</span>
                                        <span class="text-[var(--text-muted)] ml-2">(${ user.recordings_count} 录音文件)</span>
                                    </div>
                                </div>
                                <div v-if="stats.top_users.length === 0" class="text-center text-sm text-[var(--text-muted)] p-2">
                                    No data available
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- System Settings Tab -->
                <div v-show="activeTab === 'settings'">
                    <div class="flex justify-between items-center mb-4">
                        <h3 class="text-lg font-medium text-[var(--text-secondary)]">${t('adminDashboard.systemSettings')}</h3>
                        <button @click="loadSettings" class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-lg shadow hover:bg-[var(--bg-button-hover)] focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] focus:ring-offset-2 transition duration-150 ease-in-out">
                            <i class="fas fa-sync-alt mr-2"></i> ${t('buttons.refresh')}
                        </button>
                    </div>
                    
                    <!-- Settings List -->
                    <div class="space-y-4">
                        <div v-for="setting in settings" :key="setting.id" class="bg-[var(--bg-tertiary)] p-4 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex justify-between items-start">
                                <div class="flex-grow">
                                    <h4 class="text-md font-medium text-[var(--text-primary)] mb-1">${ setting.key }</h4>
                                    <p class="text-sm text-[var(--text-muted)] mb-2">${ getSettingDescription(setting) }</p>
                                    <div class="flex items-center space-x-2">
                                        <span class="text-xs px-2 py-1 bg-[var(--bg-accent)] text-[var(--text-accent)] rounded">${ setting.setting_type }</span>
                                        <span class="text-xs text-[var(--text-muted)]">${t('adminDashboard.lastUpdated')}: ${ formatDate(setting.updated_at) }</span>
                                    </div>
                                </div>
                                <div class="ml-4 flex items-center space-x-2">
                                    <div class="text-right">
                                        <div class="text-sm font-medium text-[var(--text-primary)]">
                                            <span v-if="setting.setting_type === 'boolean'">
                                                <span v-if="setting.value === 'true'" class="text-[var(--text-success-strong)]">
                                                    <i class="fas fa-check-circle mr-1"></i> Enabled
                                                </span>
                                                <span v-else class="text-[var(--text-danger-strong)]">
                                                    <i class="fas fa-times-circle mr-1"></i> Disabled
                                                </span>
                                            </span>
                                            <span v-else-if="setting.key === 'transcript_length_limit' && setting.value === '-1'" class="text-[var(--text-info-strong)]">
                                                <i class="fas fa-infinity mr-1"></i> ${t('adminDashboard.noLimit')}
                                            </span>
                            <span v-else-if="setting.key === 'transcript_length_limit'" class="text-[var(--text-primary)]">
                                ${ Number(setting.value).toLocaleString() } ${t('adminDashboard.characters')}
                            </span>
                            <span v-else-if="setting.key === 'max_file_size_mb'" class="text-[var(--text-primary)]">
                                ${ Number(setting.value).toLocaleString() } ${t('adminDashboard.megabytes')}
                            </span>
                            <span v-else-if="setting.key === 'asr_timeout_seconds'" class="text-[var(--text-primary)]">
                                ${ Number(setting.value).toLocaleString() } ${t('adminDashboard.seconds')}
                            </span>
                                            <span v-else>${ setting.value || t('adminDashboard.notSet') }</span>
                                        </div>
                                    </div>
                                    <button @click="editSetting(setting)" class="text-[var(--text-accent)] hover:text-[var(--text-accent-hover)] p-1" :title="t('buttons.editSetting')">
                                        <i class="fas fa-edit"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                        
                        <div v-if="settings.length === 0" class="text-center py-8">
                            <div v-if="isLoadingSettings">
                                <i class="fas fa-spinner fa-spin mr-2"></i> Loading settings...
                            </div>
                            <div v-else class="text-[var(--text-muted)]">
                                No system settings found.
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Default Prompts Tab -->
                <div v-show="activeTab === 'prompts'">
                    <div class="mb-6">
                        <h3 class="text-lg font-medium text-[var(--text-secondary)] mb-4">${t('adminDashboard.defaultPrompts')}</h3>
                        <div class="bg-[var(--bg-info-light)] text-[var(--text-info-strong)] p-4 rounded-lg mb-4">
                            <i class="fas fa-info-circle mr-2"></i>
                            ${t('adminDashboard.defaultPromptInfo')}
                        </div>
                    </div>
                    
                    <div class="bg-[var(--bg-tertiary)] p-6 rounded-lg border border-[var(--border-primary)]">
                        <div class="mb-4">
                            <label class="block text-sm font-medium text-[var(--text-secondary)] mb-2">
                                ${t('adminDashboard.defaultSummarizationPrompt')}
                            </label>
                            <p class="text-sm text-[var(--text-muted)] mb-3">
                                ${t('adminDashboard.promptDescription')}
                            </p>
                            <textarea 
                                v-model="defaultSummaryPrompt"
                                rows="8"
                                class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                :placeholder="t('form.summaryPromptPlaceholder')">
                            </textarea>
                        </div>
                        
                        <div class="flex justify-between items-center">
                            <div>
                                <button @click="resetDefaultPrompt" 
                                        class="px-4 py-2 border border-[var(--border-secondary)] text-[var(--text-secondary)] rounded-md hover:bg-[var(--bg-tertiary)]">
                                    <i class="fas fa-undo mr-2"></i> ${t('adminDashboard.resetToDefault')}
                                </button>
                            </div>
                            <div>
                                <button @click="saveDefaultPrompt" 
                                        :disabled="isSavingPrompt"
                                        class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-md hover:bg-[var(--bg-button-hover)] disabled:opacity-50 disabled:cursor-not-allowed">
                                    <i v-if="isSavingPrompt" class="fas fa-spinner fa-spin mr-2"></i>
                                    <i v-else class="fas fa-save mr-2"></i>
                                    ${ isSavingPrompt ? t('adminDashboard.saving') : t('buttons.saveChanges') }
                                </button>
                            </div>
                        </div>
                        
                        <div v-if="promptSaveMessage" class="mt-4">
                            <div :class="promptSaveError ? 'bg-[var(--bg-danger-light)] text-[var(--text-danger-strong)]' : 'bg-[var(--bg-success-light)] text-[var(--text-success-strong)]'" 
                                 class="p-3 rounded-md text-sm">
                                ${ promptSaveMessage }
                            </div>
                        </div>
                    </div>
                    
                    <div class="mt-6 bg-[var(--bg-tertiary)] p-6 rounded-lg border border-[var(--border-primary)]">
                        <h4 class="text-md font-medium text-[var(--text-secondary)] mb-3">${t('adminDashboard.promptHierarchy')}</h4>
                        <p class="text-sm text-[var(--text-muted)] mb-3">
                            ${t('adminDashboard.promptPriorityDescription')}
                        </p>
                        <ol class="list-decimal list-inside space-y-2 text-sm text-[var(--text-secondary)]">
                            <li><strong>${t('adminDashboard.tagCustomPrompt')}:</strong> ${t('adminDashboard.tagCustomPromptDesc')}</li>
                            <li><strong>${t('adminDashboard.userCustomPrompt')}:</strong> ${t('adminDashboard.userCustomPromptDesc')}</li>
                            <li><strong>${t('adminDashboard.adminDefaultPrompt')}:</strong> ${t('adminDashboard.adminDefaultPromptDesc')}</li>
                            <li><strong>${t('adminDashboard.systemFallback')}:</strong> ${t('adminDashboard.systemFallbackDesc')}</li>
                        </ol>
                    </div>
                    
                    <!-- Full LLM Prompt Structure Expander -->
                    <div class="mt-6 bg-[var(--bg-tertiary)] rounded-lg border border-[var(--border-primary)]">
                        <button @click="showFullPromptStructure = !showFullPromptStructure" 
                                class="w-full p-6 flex justify-between items-center hover:bg-[var(--bg-quaternary)] transition-colors duration-200">
                            <h4 class="text-md font-medium text-[var(--text-secondary)]">
                                <i class="fas fa-code mr-2"></i>
                                ${t('adminDashboard.viewFullPromptStructure')}
                            </h4>
                            <i :class="showFullPromptStructure ? 'fas fa-chevron-up' : 'fas fa-chevron-down'" 
                               class="text-[var(--text-muted)]"></i>
                        </button>
                        
                        <div v-show="showFullPromptStructure" class="border-t border-[var(--border-primary)]">
                            <div class="p-6 space-y-6">
                                <div>
                                    <h5 class="text-sm font-semibold text-[var(--text-accent)] mb-2">${t('adminDashboard.systemPrompt')}:</h5>
                                    <div class="bg-[var(--bg-secondary)] p-4 rounded-md border border-[var(--border-secondary)]">
                                        <pre class="text-xs text-[var(--text-secondary)] whitespace-pre-wrap font-mono">You are an AI assistant that generates comprehensive summaries for meeting transcripts. Respond only with the summary in Markdown format. Do NOT use markdown code blocks (```markdown). Provide raw markdown content directly.

Context:
- Current date: {current_date}
- Tags applied to this transcript by the user: {tag_names} <span class="text-[var(--text-muted)]">(if tags exist)</span>
- Information about the user: Name: {name}, Job title: {job_title}, Company: {company} <span class="text-[var(--text-muted)]">(if provided)</span>

<span class="text-[var(--text-muted)]">Language Requirement: You MUST generate the entire summary in {user_output_language}. This is mandatory. (if language preference is set)</span></pre>
                                    </div>
                                </div>
                                
                                <div>
                                    <h5 class="text-sm font-semibold text-[var(--text-accent)] mb-2">${t('adminDashboard.userMessageTemplate')}:</h5>
                                    <div class="bg-[var(--bg-secondary)] p-4 rounded-md border border-[var(--border-secondary)]">
                                        <pre class="text-xs text-[var(--text-secondary)] whitespace-pre-wrap font-mono">Transcription:
"""
{transcript_text}
"""

Summarization Instructions:
<span class="text-[var(--text-muted)]">/* This section is dynamically replaced with one of the following (in order of priority):
   1. Combined tag prompts (if tags with custom prompts are selected)
   2. User's personal summarization prompt (if set in account settings)
   3. Admin default prompt (shown below)
   4. System fallback prompt */</span>
<span v-if="defaultSummaryPrompt || originalDefaultPrompt">${ defaultSummaryPrompt || originalDefaultPrompt }</span>

<span class="text-[var(--text-muted)]">{language_directive} (e.g., "Ensure your response is in {language}." if language is set)</span></pre>
                                    </div>
                                    <p class="text-xs text-[var(--text-muted)] mt-2">
                                        <i class="fas fa-info-circle mr-1"></i>
                                        ${t('adminDashboard.placeholdersNote')}
                                    </p>
                                </div>
                                
                                <div>
                                    <h5 class="text-sm font-semibold text-[var(--text-accent)] mb-2">${t('adminDashboard.additionalContext')}:</h5>
                                    <div class="bg-[var(--bg-info-light)] p-4 rounded-md">
                                        <ul class="text-xs text-[var(--text-info-strong)] space-y-2">
                                            <li><i class="fas fa-check-circle mr-1"></i> ${t('adminDashboard.contextNotes.transcriptLimit')}</li>
                                            <li><i class="fas fa-check-circle mr-1"></i> ${t('adminDashboard.contextNotes.jsonConversion')}</li>
                                            <li><i class="fas fa-check-circle mr-1"></i> ${t('adminDashboard.contextNotes.tagPrompts')}</li>
                                            <li><i class="fas fa-check-circle mr-1"></i> ${t('adminDashboard.contextNotes.modelConfig')}</li>
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- Vector Store Tab -->
                <div v-show="activeTab === 'vectorstore'" v-if="inquireModeEnabled">
                    <div class="flex justify-between items-center mb-6">
                        <h3 class="text-lg font-medium text-[var(--text-secondary)]">${t('adminDashboard.vectorStoreManagement')}</h3>
                        <button @click="loadInquireStatus" class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-lg shadow hover:bg-[var(--bg-button-hover)] focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] focus:ring-offset-2 transition duration-150 ease-in-out">
                            <i class="fas fa-sync-alt mr-2"></i> ${t('adminDashboard.refreshStatus')}
                        </button>
                    </div>
                    
                    <!-- Vector Store Info -->
                    <div class="bg-[var(--bg-tertiary)] p-6 rounded-lg border border-[var(--border-primary)] mb-6">
                        <h4 class="text-md font-semibold text-[var(--text-primary)] mb-4">
                            <i class="fas fa-info-circle mr-2"></i>${t('adminDashboard.aboutInquireMode')}
                        </h4>
                        <p class="text-sm text-[var(--text-secondary)] mb-3">
                            ${t('adminDashboard.inquireModeDescription')}
                        </p>
                        <div class="grid grid-cols-2 gap-4 text-sm">
                            <div>
                                <span class="text-[var(--text-muted)]">${t('adminDashboard.chunkSize')}:</span>
                                <span class="ml-2 text-[var(--text-primary)]">500 ${t('adminDashboard.characters')}</span>
                            </div>
                            <div>
                                <span class="text-[var(--text-muted)]">${t('adminDashboard.overlap')}:</span>
                                <span class="ml-2 text-[var(--text-primary)]">50 ${t('adminDashboard.characters')}</span>
                            </div>
                            <div>
                                <span class="text-[var(--text-muted)]">${t('adminDashboard.embeddingModel')}:</span>
                                <span class="ml-2 text-[var(--text-primary)]">all-MiniLM-L6-v2</span>
                            </div>
                            <div>
                                <span class="text-[var(--text-muted)]">${t('adminDashboard.vectorDimensions')}:</span>
                                <span class="ml-2 text-[var(--text-primary)]">384</span>
                            </div>
                        </div>
                    </div>
                    
                    <!-- Statistics Grid -->
                    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-6">
                        <div class="bg-[var(--bg-secondary)] p-6 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center justify-between">
                                <div>
                                    <p class="text-sm text-[var(--text-muted)]">${t('adminDashboard.totalRecordings')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-primary)]">${ inquireStatus.total_completed_recordings || 0 }</p>
                                </div>
                                <i class="fas fa-file-audio text-3xl text-[var(--text-accent)] opacity-50"></i>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-secondary)] p-6 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center justify-between">
                                <div>
                                    <p class="text-sm text-[var(--text-muted)]">${t('adminDashboard.processedForInquire')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-success-strong)]">${ inquireStatus.processed_for_inquire || 0 }</p>
                                </div>
                                <i class="fas fa-check-circle text-3xl text-[var(--text-success-strong)] opacity-50"></i>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-secondary)] p-6 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center justify-between">
                                <div>
                                    <p class="text-sm text-[var(--text-muted)]">${t('adminDashboard.needProcessing')}</p>
                                    <p class="text-2xl font-semibold" :class="inquireStatus.need_processing > 0 ? 'text-[var(--text-warning-strong)]' : 'text-[var(--text-primary)]'">
                                        ${ inquireStatus.need_processing || 0 }
                                    </p>
                                </div>
                                <i class="fas fa-clock text-3xl opacity-50" :class="inquireStatus.need_processing > 0 ? 'text-[var(--text-warning-strong)]' : 'text-[var(--text-muted)]'"></i>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-secondary)] p-6 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center justify-between">
                                <div>
                                    <p class="text-sm text-[var(--text-muted)]">${t('adminDashboard.totalChunks')}</p>
                                    <p class="text-2xl font-semibold text-[var(--text-primary)]">${ inquireStatus.total_chunks || 0 }</p>
                                </div>
                                <i class="fas fa-th text-3xl text-[var(--text-accent)] opacity-50"></i>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-secondary)] p-6 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center justify-between">
                                <div>
                                    <p class="text-sm text-[var(--text-muted)]">${t('adminDashboard.embeddingsStatus')}</p>
                                    <p class="text-lg font-semibold" :class="inquireStatus.embeddings_available ? 'text-[var(--text-success-strong)]' : 'text-[var(--text-warning-strong)]'">
                                        <i :class="inquireStatus.embeddings_available ? 'fas fa-check-circle' : 'fas fa-exclamation-triangle'" class="mr-2"></i>
                                        ${ inquireStatus.embeddings_available ? t('adminDashboard.available') : t('adminDashboard.textSearchOnly') }
                                    </p>
                                </div>
                                <i class="fas fa-brain text-3xl opacity-50" :class="inquireStatus.embeddings_available ? 'text-[var(--text-success-strong)]' : 'text-[var(--text-warning-strong)]'"></i>
                            </div>
                        </div>
                        
                        <div class="bg-[var(--bg-secondary)] p-6 rounded-lg border border-[var(--border-primary)] shadow-sm">
                            <div class="flex items-center justify-between">
                                <div>
                                    <p class="text-sm text-[var(--text-muted)]">${t('adminDashboard.processingProgress')}</p>
                                    <div class="mt-2">
                                        <div class="w-full bg-[var(--bg-tertiary)] rounded-full h-2.5">
                                            <div class="bg-[var(--text-accent)] h-2.5 rounded-full" :style="{width: getProcessingProgress() + '%'}"></div>
                                        </div>
                                        <p class="text-xs text-[var(--text-muted)] mt-1">${ getProcessingProgress() }% ${t('adminDashboard.complete')}</p>
                                    </div>
                                </div>
                                <i class="fas fa-tasks text-3xl text-[var(--text-accent)] opacity-50"></i>
                            </div>
                        </div>
                    </div>
                    
                    <!-- Processing Actions -->
                    <div class="bg-[var(--bg-tertiary)] p-6 rounded-lg border border-[var(--border-primary)]">
                        <h4 class="text-md font-semibold text-[var(--text-primary)] mb-4">
                            <i class="fas fa-cog mr-2"></i>${t('adminDashboard.processingActions')}
                        </h4>
                        
                        <div v-if="inquireStatus.need_processing > 0" class="mb-4">
                            <p class="text-sm text-[var(--text-secondary)] mb-4">
                                ${t('adminDashboard.recordingsNeedProcessing').replace('{{count}}', inquireStatus.need_processing)}
                            </p>
                            
                            <div class="flex flex-wrap gap-3">
                                <button @click="processAllRecordings" 
                                        :disabled="isProcessingRecordings"
                                        class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-lg shadow hover:bg-[var(--bg-button-hover)] focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] focus:ring-offset-2 transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed">
                                    <i :class="isProcessingRecordings ? 'fas fa-spinner fa-spin' : 'fas fa-play'" class="mr-2"></i>
                                    ${ isProcessingRecordings ? t('adminDashboard.processing') : t('adminDashboard.processAllRecordings') }
                                </button>
                                
                                <button @click="processBatchRecordings(10)" 
                                        :disabled="isProcessingRecordings"
                                        class="px-4 py-2 bg-[var(--bg-secondary)] text-[var(--text-secondary)] border border-[var(--border-secondary)] rounded-lg shadow hover:bg-[var(--bg-tertiary)] focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] focus:ring-offset-2 transition duration-150 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed">
                                    <i class="fas fa-forward mr-2"></i>
                                    ${t('adminDashboard.processNext10')}
                                </button>
                            </div>
                            
                            <div v-if="processingResult" class="mt-4 p-4 rounded-lg" 
                                 :class="processingResult.success ? 'bg-[var(--bg-success-light)] text-[var(--text-success-strong)]' : 'bg-[var(--bg-danger-light)] text-[var(--text-danger-strong)]'">
                                <p class="font-medium">${ processingResult.message }</p>
                                <div v-if="processingResult.failed && processingResult.failed.length > 0" class="mt-2">
                                    <p class="text-sm font-medium">Failed recordings:</p>
                                    <ul class="text-xs mt-1 space-y-1">
                                        <li v-for="fail in processingResult.failed" :key="fail.id">
                                            ID ${ fail.id }: ${ fail.title } - ${ fail.reason }
                                        </li>
                                    </ul>
                                </div>
                            </div>
                        </div>
                        
                        <div v-else class="text-center py-4">
                            <i class="fas fa-check-circle text-4xl text-[var(--text-success-strong)] mb-3"></i>
                            <p class="text-[var(--text-success-strong)] font-medium">${t('adminDashboard.allRecordingsProcessed')}</p>
                            <p class="text-sm text-[var(--text-muted)] mt-1">${t('adminDashboard.vectorStoreUpToDate')}</p>
                        </div>
                    </div>
                </div>
            </div>
        </main>

        <footer class="text-center py-4 mt-8 text-xs text-[var(--text-light)] border-t border-[var(--border-primary)]">
            {{ html_title }} &copy; {{ now.year }}
        </footer>
        
        <!-- Add User Modal -->
        <div v-if="showAddUserModal" @click.self="showAddUserModal = false" class="fixed inset-0 bg-black bg-opacity-70 backdrop-blur-sm flex items-center justify-center z-50 p-4">
            <div class="bg-[var(--bg-secondary)] p-6 rounded-lg shadow-xl w-full max-w-md">
                <div class="flex justify-between items-center mb-4">
                    <h3 class="text-xl font-semibold text-[var(--text-primary)]">${t('adminDashboard.addNewUser')}</h3>
                    <button @click="showAddUserModal = false" class="text-[var(--text-muted)] hover:text-[var(--text-secondary)]">&times;</button>
                </div>
                <form @submit.prevent="addUser">
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.usernameLabel')}</label>
                        <input v-model="newUser.username" type="text" required class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.emailLabel')}</label>
                        <input v-model="newUser.email" type="email" required class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.passwordLabel')}</label>
                        <input v-model="newUser.password" type="password" required class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.confirmPasswordLabel')}</label>
                        <input v-model="newUser.confirmPassword" type="password" required class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="flex items-center cursor-pointer">
                            <input v-model="newUser.isAdmin" type="checkbox" class="sr-only peer">
                            <div class="relative w-11 h-6 bg-gray-600 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[var(--text-accent)]"></div>
                            <span class="ml-3 text-sm text-[var(--text-secondary)]">${t('adminDashboard.adminUser')}</span>
                        </label>
                    </div>
                    <div class="flex justify-end space-x-3">
                        <button type="button" @click="showAddUserModal = false" class="px-4 py-2 border border-[var(--border-secondary)] text-[var(--text-secondary)] rounded-md hover:bg-[var(--bg-tertiary)]">${t('buttons.cancel')}</button>
                        <button type="submit" class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-md hover:bg-[var(--bg-button-hover)]">${t('adminDashboard.addUser')}</button>
                    </div>
                </form>
            </div>
        </div>
        
        <!-- Edit User Modal -->
        <div v-if="showEditUserModal" @click.self="showEditUserModal = false" class="fixed inset-0 bg-black bg-opacity-70 backdrop-blur-sm flex items-center justify-center z-50 p-4">
            <div class="bg-[var(--bg-secondary)] p-6 rounded-lg shadow-xl w-full max-w-md">
                <div class="flex justify-between items-center mb-4">
                    <h3 class="text-xl font-semibold text-[var(--text-primary)]">${t('adminDashboard.editUser')}</h3>
                    <button @click="showEditUserModal = false" class="text-[var(--text-muted)] hover:text-[var(--text-secondary)]">&times;</button>
                </div>
                <form @submit.prevent="updateUser">
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.usernameLabel')}</label>
                        <input v-model="editingUser.username" type="text" required class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.emailLabel')}</label>
                        <input v-model="editingUser.email" type="email" required class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">${t('adminDashboard.newPasswordLabel')}</label>
                        <input v-model="editingUser.password" type="password" class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]">
                    </div>
                    <div class="mb-4">
                        <label class="flex items-center cursor-pointer">
                            <input v-model="editingUser.is_admin" type="checkbox" class="sr-only peer">
                            <div class="relative w-11 h-6 bg-gray-600 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[var(--text-accent)]"></div>
                            <span class="ml-3 text-sm text-[var(--text-secondary)]">${t('adminDashboard.adminUser')}</span>
                        </label>
                    </div>
                    <div class="flex justify-end space-x-3">
                        <button type="button" @click="showEditUserModal = false" class="px-4 py-2 border border-[var(--border-secondary)] text-[var(--text-secondary)] rounded-md hover:bg-[var(--bg-tertiary)]">取消</button>
                        <button type="submit" class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-md hover:bg-[var(--bg-button-hover)]">${t('adminDashboard.updateUser')}</button>
                    </div>
                </form>
            </div>
        </div>
        
        <!-- Delete User Confirmation Modal -->
        <div v-if="showDeleteUserModal" @click.self="showDeleteUserModal = false" class="fixed inset-0 bg-black bg-opacity-70 backdrop-blur-sm flex items-center justify-center z-50 p-4">
            <div class="bg-[var(--bg-secondary)] p-6 rounded-lg shadow-xl w-full max-w-md">
                <div class="flex justify-between items-center mb-4">
                    <h3 class="text-xl font-semibold text-[var(--text-primary)]">Confirm Delete</h3>
                    <button @click="showDeleteUserModal = false" class="text-[var(--text-muted)] hover:text-[var(--text-secondary)]">&times;</button>
                </div>
                <p class="mb-4 text-[var(--text-secondary)]">Are you sure you want to delete the user <span class="font-semibold">${ userToDelete?.username }</span>? This action cannot be undone.</p>
                <div class="flex justify-end space-x-3">
                    <button @click="showDeleteUserModal = false" class="px-4 py-2 border border-[var(--border-secondary)] text-[var(--text-secondary)] rounded-md hover:bg-[var(--bg-tertiary)]">取消</button>
                    <button @click="deleteUser" class="px-4 py-2 bg-[var(--bg-danger)] text-[var(--text-button)] rounded-md hover:bg-[var(--bg-danger-hover)]">Delete User</button>
                </div>
            </div>
        </div>
        
        <!-- Edit System Setting Modal -->
        <div v-if="showEditSettingModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
            <div class="bg-[var(--bg-secondary)] p-6 rounded-lg shadow-xl w-full max-w-lg max-h-[80vh] flex flex-col">
                <div class="flex justify-between items-center mb-4 flex-shrink-0">
                    <h3 class="text-xl font-semibold text-[var(--text-primary)]">编辑系统设置</h3>
                    <button @click="showEditSettingModal = false" class="text-[var(--text-muted)] hover:text-[var(--text-secondary)] text-2xl leading-none">&times;</button>
                </div>
                
                <div v-if="editingSetting" class="space-y-4 overflow-y-auto flex-1 min-h-0 pr-2">
                    <div>
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">Setting Key</label>
                        <div class="px-3 py-2 bg-[var(--bg-tertiary)] text-[var(--text-muted)] rounded-md font-mono text-sm">
                            ${ editingSetting.key }
                        </div>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">Description</label>
                        <div class="px-3 py-2 text-[var(--text-muted)] text-sm">
                            ${ editingSetting.description || 'No description available' }
                        </div>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">Type</label>
                        <span class="inline-block px-2 py-1 bg-[var(--bg-accent)] text-[var(--text-accent)] rounded text-xs">
                            ${ editingSetting.setting_type }
                        </span>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-1">Current Value</label>
                        <div class="px-3 py-2 bg-[var(--bg-tertiary)] text-[var(--text-muted)] rounded-md max-h-32 overflow-y-auto">
                            <span v-if="editingSetting.key === 'transcript_length_limit' && editingSetting.value === '-1'">
                                ${t('adminDashboard.noLimit')}
                            </span>
                            <span v-else-if="editingSetting.key === 'transcript_length_limit'">
                                ${ Number(editingSetting.value).toLocaleString() } ${t('adminDashboard.characters')}
                            </span>
                            <span v-else-if="editingSetting.key === 'max_file_size_mb'">
                                ${ Number(editingSetting.value).toLocaleString() } ${t('adminDashboard.megabytes')}
                            </span>
                            <span v-else-if="editingSetting.key === 'asr_timeout_seconds'">
                                ${ Number(editingSetting.value).toLocaleString() } ${t('adminDashboard.seconds')} (${ Math.round(Number(editingSetting.value) / 60) } ${t('adminDashboard.minutes')})
                            </span>
                            <span v-else>${ editingSetting.value || t('adminDashboard.notSet') }</span>
                        </div>
                    </div>
                    
                    <div>
                        <label class="block text-sm font-medium text-[var(--text-secondary)] mb-2">New Value</label>
                        
                        <!-- Boolean type -->
                        <div v-if="editingSetting.setting_type === 'boolean'" class="flex items-center space-x-4">
                            <label class="flex items-center cursor-pointer">
                                <input v-model="settingNewValue" type="radio" value="true" class="mr-2 text-[var(--text-accent)] focus:ring-[var(--border-focus)]">
                                <span class="text-[var(--text-primary)]">Enabled</span>
                            </label>
                            <label class="flex items-center cursor-pointer">
                                <input v-model="settingNewValue" type="radio" value="false" class="mr-2 text-[var(--text-accent)] focus:ring-[var(--border-focus)]">
                                <span class="text-[var(--text-primary)]">Disabled</span>
                            </label>
                        </div>
                        
                        <!-- Integer/Float type with special handling for specific keys -->
                        <div v-else-if="editingSetting.setting_type === 'integer' || editingSetting.setting_type === 'float'" class="space-y-2">
                            <!-- Special input for transcript_length_limit -->
                            <div v-if="editingSetting.key === 'transcript_length_limit'" class="space-y-2">
                                <div class="flex items-center space-x-2">
                                    <input v-model="settingUseNoLimit" type="checkbox" id="noLimit" class="rounded border-[var(--border-secondary)] text-[var(--text-accent)] focus:ring-[var(--border-focus)]">
                                    <label for="noLimit" class="text-sm text-[var(--text-secondary)]">No limit (use entire transcript)</label>
                                </div>
                                <input v-if="!settingUseNoLimit" v-model.number="settingNewValue" type="number" min="1000" step="1000" 
                                       class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                       :placeholder="t('form.placeholderCharacterLimit')">
                                <small v-if="!settingUseNoLimit" class="text-[var(--text-muted)]">Recommended: 30000-50000 characters for most LLMs</small>
                            </div>
                            
                            <!-- Special input for max_file_size_mb -->
                            <div v-else-if="editingSetting.key === 'max_file_size_mb'" class="space-y-2">
                                <input v-model.number="settingNewValue" type="number" min="1" max="10000" step="50"
                                       class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                       :placeholder="t('form.placeholderSizeMB')">
                                <small class="text-[var(--text-muted)]">${t('adminDashboard.maxFileSizeHelp')}</small>
                            </div>
                            
                            <!-- Special input for asr_timeout_seconds -->
                            <div v-else-if="editingSetting.key === 'asr_timeout_seconds'" class="space-y-2">
                                <div class="flex space-x-2">
                                    <div class="flex-1">
                                        <input v-model.number="settingTimeoutMinutes" type="number" min="1" max="600" step="1"
                                               class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                               :placeholder="t('form.placeholderMinutes')">
                                        <small class="text-[var(--text-muted)]">${t('adminDashboard.minutes')}</small>
                                    </div>
                                    <div class="flex-1">
                                        <input v-model.number="settingTimeoutSeconds" type="number" min="0" max="59" step="1"
                                               class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                               :placeholder="t('form.placeholderSeconds')">
                                        <small class="text-[var(--text-muted)]">${t('adminDashboard.seconds')}</small>
                                    </div>
                                </div>
                                <div class="text-sm text-[var(--text-muted)]">
                                    ${t('adminDashboard.total')}: <span class="font-medium text-[var(--text-primary)]">${ (settingTimeoutMinutes * 60 + settingTimeoutSeconds).toLocaleString() } ${t('adminDashboard.seconds')}</span>
                                </div>
                                <small class="text-[var(--text-muted)]">${t('adminDashboard.timeoutRecommendation')}</small>
                            </div>
                            
                            <!-- Default number input -->
                            <input v-else v-model.number="settingNewValue" :type="editingSetting.setting_type === 'integer' ? 'number' : 'text'" 
                                   class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                   :placeholder="`Enter ${editingSetting.setting_type} value`">
                        </div>
                        
                        <!-- String type -->
                        <textarea v-else v-model="settingNewValue" rows="6"
                                  class="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--border-focus)] bg-[var(--bg-input)] text-[var(--text-primary)]"
                                  :placeholder="'Enter value'"></textarea>
                    </div>
                    
                    <div v-if="settingError" class="p-3 bg-[var(--bg-danger-light)] text-[var(--text-danger-strong)] rounded-md text-sm">
                        ${ settingError }
                    </div>
                </div>
                
                <div class="flex justify-end space-x-3 mt-6 pt-4 border-t border-[var(--border-primary)] flex-shrink-0">
                    <button @click="showEditSettingModal = false" 
                            class="px-4 py-2 border border-[var(--border-secondary)] text-[var(--text-secondary)] rounded-md hover:bg-[var(--bg-tertiary)]">
                        取消
                    </button>
                    <button @click="saveSettingValue" 
                            class="px-4 py-2 bg-[var(--bg-button)] text-[var(--text-button)] rounded-md hover:bg-[var(--bg-button-hover)]">
                        ${t('buttons.saveChanges')}
                    </button>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        const { createApp, ref, computed, onMounted, watch } = Vue
        
        // Initialize i18n before Vue app creation
        initializeI18n().then(() => {
            // Get the i18n instance to properly bind the t function
            const i18nInstance = window.i18n;
            
            createApp({
            setup() {
                
                // State
                const activeTab = ref('users');
                const users = ref([]);
                const stats = ref({
                    total_users: 0,
                    total_recordings: 0,
                    total_storage: 0,
                    total_queries: 0,
                    completed_recordings: 0,
                    processing_recordings: 0,
                    pending_recordings: 0,
                    failed_recordings: 0,
                    top_users: []
                });
                const settings = ref([]);
                const isLoadingUsers = ref(true);
                const isLoadingSettings = ref(false);
                const userSearchQuery = ref('');
                const isDarkMode = ref(false);
                const isUserMenuOpen = ref(false);
                
                // Modal state
                const showAddUserModal = ref(false);
                const showEditUserModal = ref(false);
                const showDeleteUserModal = ref(false);
                const newUser = ref({
                    username: '',
                    email: '',
                    password: '',
                    confirmPassword: '',
                    isAdmin: false
                });
                const editingUser = ref(null);
                const userToDelete = ref(null);
                
                // Inquire Mode state
                const inquireModeEnabled = ref({{ 'true' if inquire_mode_enabled else 'false' }});
                const inquireStatus = ref({
                    total_completed_recordings: 0,
                    recordings_with_transcriptions: 0,
                    processed_for_inquire: 0,
                    need_processing: 0,
                    total_chunks: 0,
                    embeddings_available: false
                });
                const isProcessingRecordings = ref(false);
                const processingResult = ref(null);
                
                // Default Prompts state
                const defaultSummaryPrompt = ref('');
                const isSavingPrompt = ref(false);
                const promptSaveMessage = ref('');
                const promptSaveError = ref(false);
                const showFullPromptStructure = ref(false);
                const originalDefaultPrompt = `Generate a comprehensive summary that includes the following sections:
- **Key Issues Discussed**: A bulleted list of the main topics
- **Key Decisions Made**: A bulleted list of any decisions reached
- **Action Items**: A bulleted list of tasks assigned, including who is responsible if mentioned`;
                
                // Computed properties
                const filteredUsers = computed(() => {
                    if (!userSearchQuery.value) return users.value;
                    
                    const query = userSearchQuery.value.toLowerCase();
                    return users.value.filter(user => 
                        user.username.toLowerCase().includes(query) || 
                        user.email.toLowerCase().includes(query)
                    );
                });
                
                // Methods
                const loadUsers = async () => {
                    isLoadingUsers.value = true;
                    try {
                        const response = await fetch('/tool/speakr/admin/users');
                        if (!response.ok) throw new Error('Failed to load users');
                        
                        const data = await response.json();
                        users.value = data;
                    } catch (error) {
                        console.error('Error loading users:', error);
                        // Show error notification
                    } finally {
                        isLoadingUsers.value = false;
                    }
                };
                
                const loadStats = async () => {
                    try {
                        const response = await fetch('/tool/speakr/admin/stats');
                        if (!response.ok) throw new Error('Failed to load statistics');
                        
                        const data = await response.json();
                        stats.value = data;
                    } catch (error) {
                        console.error('Error loading statistics:', error);
                        // Show error notification
                    }
                };
                
                const loadSettings = async () => {
                    isLoadingSettings.value = true;
                    try {
                        const response = await fetch('/tool/speakr/admin/settings');
                        if (response.status === 429) {
                            throw new Error('Rate limit exceeded. Please wait a moment and try again.');
                        }
                        if (!response.ok) throw new Error('Failed to load settings');
                        
                        const data = await response.json();
                        settings.value = data;
                    } catch (error) {
                        console.error('Error loading settings:', error);
                        // Show error notification
                    } finally {
                        isLoadingSettings.value = false;
                    }
                };
                
                const showEditSettingModal = ref(false);
                const editingSetting = ref(null);
                const settingNewValue = ref('');
                const settingUseNoLimit = ref(false);
                const settingTimeoutMinutes = ref(30);
                const settingTimeoutSeconds = ref(0);
                const settingError = ref('');
                
                const editSetting = (setting) => {
                    editingSetting.value = { ...setting };
                    settingError.value = '';
                    
                    // Initialize form values based on setting type and key
                    if (setting.key === 'transcript_length_limit') {
                        if (setting.value === '-1') {
                            settingUseNoLimit.value = true;
                            settingNewValue.value = 30000; // Default if unchecked
                        } else {
                            settingUseNoLimit.value = false;
                            settingNewValue.value = parseInt(setting.value) || 30000;
                        }
                    } else if (setting.key === 'asr_timeout_seconds') {
                        const totalSeconds = parseInt(setting.value) || 1800;
                        settingTimeoutMinutes.value = Math.floor(totalSeconds / 60);
                        settingTimeoutSeconds.value = totalSeconds % 60;
                    } else if (setting.setting_type === 'boolean') {
                        settingNewValue.value = setting.value || 'false';
                    } else {
                        settingNewValue.value = setting.value || '';
                    }
                    
                    showEditSettingModal.value = true;
                };
                
                const saveSettingValue = async () => {
                    settingError.value = '';
                    
                    let finalValue;
                    
                    // Validate and prepare the value based on setting type
                    if (editingSetting.value.key === 'transcript_length_limit') {
                        if (settingUseNoLimit.value) {
                            finalValue = '-1';
                        } else {
                            const num = parseInt(settingNewValue.value);
                            if (isNaN(num) || num < 1000) {
                                settingError.value = 'Please enter a valid number of at least 1000 characters';
                                return;
                            }
                            finalValue = num.toString();
                        }
                    } else if (editingSetting.value.key === 'max_file_size_mb') {
                        const num = parseInt(settingNewValue.value);
                        if (isNaN(num) || num < 1 || num > 10000) {
                            settingError.value = 'Please enter a valid size between 1 and 10000 MB';
                            return;
                        }
                        finalValue = num.toString();
                    } else if (editingSetting.value.key === 'asr_timeout_seconds') {
                        const totalSeconds = (settingTimeoutMinutes.value * 60) + settingTimeoutSeconds.value;
                        if (totalSeconds < 60) {
                            settingError.value = 'Timeout must be at least 60 seconds';
                            return;
                        }
                        if (totalSeconds > 36000) {
                            settingError.value = 'Timeout cannot exceed 10 hours (36000 seconds)';
                            return;
                        }
                        finalValue = totalSeconds.toString();
                    } else if (editingSetting.value.setting_type === 'integer') {
                        const num = parseInt(settingNewValue.value);
                        if (isNaN(num)) {
                            settingError.value = 'Please enter a valid integer';
                            return;
                        }
                        finalValue = num.toString();
                    } else if (editingSetting.value.setting_type === 'float') {
                        const num = parseFloat(settingNewValue.value);
                        if (isNaN(num)) {
                            settingError.value = 'Please enter a valid number';
                            return;
                        }
                        finalValue = num.toString();
                    } else {
                        finalValue = settingNewValue.value;
                    }
                    
                    // Save the setting
                    await updateSetting(
                        editingSetting.value.key,
                        finalValue,
                        editingSetting.value.description,
                        editingSetting.value.setting_type
                    );
                    
                    showEditSettingModal.value = false;
                };
                
                const updateSetting = async (key, value, description, settingType) => {
                    try {
                        // Get CSRF token
                        const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content');
                        
                        const headers = {
                            'Content-Type': 'application/json'
                        };
                        
                        if (csrfToken) {
                            headers['X-CSRFToken'] = csrfToken;
                        }
                        
                        const response = await fetch('/tool/speakr/admin/settings', {
                            method: 'POST',
                            headers: headers,
                            body: JSON.stringify({
                                key: key,
                                value: value,
                                description: description,
                                setting_type: settingType
                            })
                        });
                        
                        if (!response.ok) {
                            const errorData = await response.json();
                            throw new Error(errorData.error || 'Failed to update setting');
                        }
                        
                        // Reload settings
                        await loadSettings();
                        
                    } catch (error) {
                        console.error('Error updating setting:', error);
                        alert(error.message);
                    }
                };
                
                const formatDate = (dateString) => {
                    if (!dateString) return t('adminDashboard.never');
                    const date = new Date(dateString);
                    return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
                };
                
                const getSettingDescription = (setting) => {
                    // Map setting keys to translation keys
                    const descriptionKeys = {
                        'transcript_length_limit': 'adminDashboard.settings.transcriptLengthLimitDesc',
                        'max_file_size_mb': 'adminDashboard.settings.maxFileSizeDesc',
                        'asr_timeout_seconds': 'adminDashboard.settings.asrTimeoutDesc',
                        'admin_default_summary_prompt': 'adminDashboard.settings.defaultSummaryPromptDesc',
                        'recording_disclaimer': 'adminDashboard.settings.recordingDisclaimerDesc'
                    };
                    
                    const key = descriptionKeys[setting.key];
                    return key ? t(key) : setting.description || t('adminDashboard.noDescriptionAvailable');
                };
                
                const addUser = async () => {
                    if (newUser.value.password !== newUser.value.confirmPassword) {
                        alert('Passwords do not match');
                        return;
                    }
                    
                    try {
                        // Get CSRF token
                        const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content');
                        
                        const headers = {
                            'Content-Type': 'application/json'
                        };
                        
                        if (csrfToken) {
                            headers['X-CSRFToken'] = csrfToken;
                        }
                        
                        const response = await fetch('/tool/speakr/admin/users', {
                            method: 'POST',
                            headers: headers,
                            body: JSON.stringify({
                                username: newUser.value.username,
                                email: newUser.value.email,
                                password: newUser.value.password,
                                is_admin: newUser.value.isAdmin
                            })
                        });
                        
                        if (!response.ok) {
                            const errorData = await response.json();
                            throw new Error(errorData.error || 'Failed to add user');
                        }
                        
                        // Reset form and close modal
                        newUser.value = {
                            username: '',
                            email: '',
                            password: '',
                            confirmPassword: '',
                            isAdmin: false
                        };
                        showAddUserModal.value = false;
                        
                        // Reload users
                        await loadUsers();
                        await loadStats();
                        
                    } catch (error) {
                        console.error('Error adding user:', error);
                        alert(error.message);
                    }
                };
                
                const editUser = (user) => {
                    editingUser.value = { ...user, password: '' };
                    showEditUserModal.value = true;
                };
                
                const updateUser = async () => {
                    try {
                        const payload = {
                            username: editingUser.value.username,
                            email: editingUser.value.email,
                            is_admin: editingUser.value.is_admin
                        };
                        
                        // Only include password if it was changed
                        if (editingUser.value.password) {
                            payload.password = editingUser.value.password;
                        }
                        
                        // Get CSRF token
                        const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content');
                        
                        const headers = {
                            'Content-Type': 'application/json'
                        };
                        
                        if (csrfToken) {
                            headers['X-CSRFToken'] = csrfToken;
                        }
                        
                        const response = await fetch(`/tool/speakr/admin/users/${editingUser.value.id}`, {
                            method: 'PUT',
                            headers: headers,
                            body: JSON.stringify(payload)
                        });
                        
                        if (!response.ok) {
                            const errorData = await response.json();
                            throw new Error(errorData.error || 'Failed to update user');
                        }
                        
                        // Close modal and reload users
                        showEditUserModal.value = false;
                        await loadUsers();
                        
                    } catch (error) {
                        console.error('Error updating user:', error);
                        alert(error.message);
                    }
                };
                
                const confirmDeleteUser = (user) => {
                    userToDelete.value = user;
                    showDeleteUserModal.value = true;
                };
                
                const deleteUser = async () => {
                    try {
                        // Get CSRF token
                        const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content');
                        
                        const headers = {};
                        
                        if (csrfToken) {
                            headers['X-CSRFToken'] = csrfToken;
                        }
                        
                        const response = await fetch(`/tool/speakr/admin/users/${userToDelete.value.id}`, {
                            method: 'DELETE',
                            headers: headers
                        });
                        
                        if (!response.ok) {
                            const errorData = await response.json();
                            throw new Error(errorData.error || 'Failed to delete user');
                        }
                        
                        // Close modal and reload users
                        showDeleteUserModal.value = false;
                        await loadUsers();
                        await loadStats();
                        
                    } catch (error) {
                        console.error('Error deleting user:', error);
                        alert(error.message);
                    }
                };
                
                const toggleAdminStatus = async (user) => {
                    try {
                        // Get CSRF token
                        const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content');
                        
                        const headers = {};
                        
                        if (csrfToken) {
                            headers['X-CSRFToken'] = csrfToken;
                        }
                        
                        const response = await fetch(`/tool/speakr/admin/users/${user.id}/toggle-admin`, {
                            method: 'POST',
                            headers: headers
                        });
                        
                        if (!response.ok) {
                            const errorData = await response.json();
                            throw new Error(errorData.error || 'Failed to toggle admin status');
                        }
                        
                        // Reload users
                        await loadUsers();
                        
                    } catch (error) {
                        console.error('Error toggling admin status:', error);
                        alert(error.message);
                    }
                };
                
                const formatFileSize = (bytes) => {
                    if (!bytes || bytes === 0) return '0 Bytes';
                    
                    const k = 1024;
                    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
                    const i = Math.floor(Math.log(bytes) / Math.log(k));
                    
                    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
                };
                
                const toggleDarkMode = () => {
                    isDarkMode.value = !isDarkMode.value;
                    if (isDarkMode.value) {
                        document.documentElement.classList.add('dark');
                        localStorage.setItem('darkMode', 'true');
                    } else {
                        document.documentElement.classList.remove('dark');
                        localStorage.setItem('darkMode', 'false');
                    }
                };
                
                // Initialize dark mode
                const initializeDarkMode = () => {
                    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
                    const savedMode = localStorage.getItem('darkMode');
                    
                    if (savedMode === 'true' || (savedMode === null && prefersDark)) {
                        isDarkMode.value = true;
                        document.documentElement.classList.add('dark');
                    } else {
                        isDarkMode.value = false;
                        document.documentElement.classList.remove('dark');
                    }
                };
                
                // Inquire Mode methods
                // Default Prompts methods
                const loadDefaultPrompt = async () => {
                    try {
                        // Use already loaded settings if available, otherwise load them
                        let settingsData = settings.value;
                        
                        if (!settingsData || settingsData.length === 0) {
                            const response = await fetch('/tool/speakr/admin/settings');
                            if (response.status === 429) {
                                throw new Error('Rate limit exceeded. Please wait a moment and try again.');
                            }
                            if (!response.ok) throw new Error('Failed to load settings');
                            settingsData = await response.json();
                            settings.value = settingsData;
                        }
                        
                        const promptSetting = settingsData.find(s => s.key === 'admin_default_summary_prompt');
                        if (promptSetting) {
                            defaultSummaryPrompt.value = promptSetting.value || '';
                        }
                    } catch (error) {
                        console.error('Error loading default prompt:', error);
                        promptSaveMessage.value = t('adminDashboard.errors.failedToLoadPrompt');
                        promptSaveError.value = true;
                    }
                };
                
                const saveDefaultPrompt = async () => {
                    isSavingPrompt.value = true;
                    promptSaveMessage.value = '';
                    promptSaveError.value = false;
                    
                    try {
                        const response = await fetch('/tool/speakr/admin/settings', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').content
                            },
                            body: JSON.stringify({
                                key: 'admin_default_summary_prompt',
                                value: defaultSummaryPrompt.value,
                                description: 'Default summarization prompt used when users have not set their own prompt. This serves as the base prompt for all users.',
                                setting_type: 'string'
                            })
                        });
                        
                        if (!response.ok) throw new Error('Failed to save prompt');
                        
                        promptSaveMessage.value = t('adminDashboard.promptSavedSuccessfully');
                        promptSaveError.value = false;
                        
                        // Clear message after 3 seconds
                        setTimeout(() => {
                            promptSaveMessage.value = '';
                        }, 3000);
                    } catch (error) {
                        console.error('Error saving default prompt:', error);
                        promptSaveMessage.value = t('adminDashboard.errors.failedToSavePrompt');
                        promptSaveError.value = true;
                    } finally {
                        isSavingPrompt.value = false;
                    }
                };
                
                const resetDefaultPrompt = () => {
                    defaultSummaryPrompt.value = originalDefaultPrompt;
                    promptSaveMessage.value = t('adminDashboard.promptResetMessage');
                    promptSaveError.value = false;
                };
                
                const loadInquireStatus = async () => {
                    try {
                        const response = await fetch('/tool/speakr/admin/inquire/status');
                        if (!response.ok) throw new Error('Failed to load inquire status');
                        
                        const data = await response.json();
                        inquireStatus.value = data;
                    } catch (error) {
                        console.error('Error loading inquire status:', error);
                    }
                };
                
                const processAllRecordings = async () => {
                    if (isProcessingRecordings.value) return;
                    
                    isProcessingRecordings.value = true;
                    processingResult.value = null;
                    
                    try {
                        const response = await fetch('/tool/speakr/admin/inquire/process-recordings', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                            },
                            body: JSON.stringify({})
                        });
                        
                        if (!response.ok) throw new Error('Failed to process recordings');
                        
                        const data = await response.json();
                        processingResult.value = data;
                        
                        // Reload status after processing
                        await loadInquireStatus();
                    } catch (error) {
                        console.error('Error processing recordings:', error);
                        processingResult.value = {
                            success: false,
                            message: 'Failed to process recordings. Please try again.'
                        };
                    } finally {
                        isProcessingRecordings.value = false;
                    }
                };
                
                const processBatchRecordings = async (batchSize) => {
                    if (isProcessingRecordings.value) return;
                    
                    isProcessingRecordings.value = true;
                    processingResult.value = null;
                    
                    try {
                        const response = await fetch('/tool/speakr/admin/inquire/process-recordings', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
                            },
                            body: JSON.stringify({ max_recordings: batchSize })
                        });
                        
                        if (!response.ok) throw new Error('Failed to process recordings');
                        
                        const data = await response.json();
                        processingResult.value = data;
                        
                        // Reload status after processing
                        await loadInquireStatus();
                    } catch (error) {
                        console.error('Error processing recordings:', error);
                        processingResult.value = {
                            success: false,
                            message: 'Failed to process recordings. Please try again.'
                        };
                    } finally {
                        isProcessingRecordings.value = false;
                    }
                };
                
                const getProcessingProgress = () => {
                    const total = (inquireStatus.value.processed_for_inquire || 0) + (inquireStatus.value.need_processing || 0);
                    if (total === 0) return 100;
                    return Math.round((inquireStatus.value.processed_for_inquire / total) * 100);
                };
                
                // Lifecycle hooks - MUST be registered before any await statements
                onMounted(async () => {
                    loadUsers();
                    loadStats();
                    initializeDarkMode();

                    // Load settings first, then default prompt can use that data
                    if (activeTab.value === 'settings' || activeTab.value === 'prompts') {
                        await loadSettings();
                    }
                    loadDefaultPrompt();

                    if (inquireModeEnabled.value) {
                        loadInquireStatus();
                    }

                    // Setup scroll indicators for tabs
                    const tabsContainer = document.getElementById('admin-tabs-container');
                    const leftIndicator = document.getElementById('admin-left-scroll-indicator');
                    const rightIndicator = document.getElementById('admin-right-scroll-indicator');

                    function updateScrollIndicators() {
                        if (tabsContainer && leftIndicator && rightIndicator) {
                            const scrollLeft = tabsContainer.scrollLeft;
                            const scrollWidth = tabsContainer.scrollWidth;
                            const clientWidth = tabsContainer.clientWidth;

                            // Show/hide left indicator
                            if (scrollLeft > 10) {
                                leftIndicator.classList.remove('opacity-0');
                                leftIndicator.classList.add('opacity-100');
                            } else {
                                leftIndicator.classList.remove('opacity-100');
                                leftIndicator.classList.add('opacity-0');
                            }

                            // Show/hide right indicator
                            if (scrollWidth - scrollLeft - clientWidth > 10) {
                                rightIndicator.classList.remove('opacity-0');
                                rightIndicator.classList.add('opacity-100');
                            } else {
                                rightIndicator.classList.remove('opacity-100');
                                rightIndicator.classList.add('opacity-0');
                            }
                        }
                    }

                    if (tabsContainer) {
                        tabsContainer.addEventListener('scroll', updateScrollIndicators);
                        window.addEventListener('resize', updateScrollIndicators);
                        // Initial check
                        updateScrollIndicators();
                        setTimeout(updateScrollIndicators, 100);
                        setTimeout(updateScrollIndicators, 500);
                    }
                });
                
                // Watch for tab changes to reload data
                watch(activeTab, async (newTab) => {
                    if (newTab === 'users') {
                        loadUsers();
                    } else if (newTab === 'stats') {
                        loadStats();
                    } else if (newTab === 'settings') {
                        await loadSettings();
                    } else if (newTab === 'prompts') {
                        // If settings aren't loaded, load them first
                        if (!settings.value || settings.value.length === 0) {
                            await loadSettings();
                        }
                        loadDefaultPrompt();
                    } else if (newTab === 'vectorstore' && inquireModeEnabled.value) {
                        loadInquireStatus();
                    }
                });
                
                return {
                    // i18n - bind to i18n instance to maintain context
                    t: (key, params) => i18nInstance ? i18nInstance.t(key, params) : key,
                    
                    // State
                    activeTab,
                    users,
                    stats,
                    settings,
                    isLoadingUsers,
                    isLoadingSettings,
                    userSearchQuery,
                    isDarkMode,
                    isUserMenuOpen,
                    
                    // Modal state
                    showAddUserModal,
                    showEditUserModal,
                    showDeleteUserModal,
                    newUser,
                    editingUser,
                    userToDelete,
                    
                    // Settings modal state
                    showEditSettingModal,
                    editingSetting,
                    settingNewValue,
                    settingUseNoLimit,
                    settingTimeoutMinutes,
                    settingTimeoutSeconds,
                    settingError,
                    
                    // Inquire Mode state
                    inquireModeEnabled,
                    inquireStatus,
                    isProcessingRecordings,
                    processingResult,
                    
                    // Default Prompts state
                    defaultSummaryPrompt,
                    isSavingPrompt,
                    promptSaveMessage,
                    promptSaveError,
                    showFullPromptStructure,
                    originalDefaultPrompt,
                    
                    // Computed
                    filteredUsers,
                    getProcessingProgress,
                    
                    // Methods
                    loadUsers,
                    loadStats,
                    loadSettings,
                    editSetting,
                    saveSettingValue,
                    updateSetting,
                    formatDate,
                    getSettingDescription,
                    addUser,
                    editUser,
                    updateUser,
                    confirmDeleteUser,
                    deleteUser,
                    toggleAdminStatus,
                    formatFileSize,
                    toggleDarkMode,
                    
                    // Inquire Mode methods
                    loadInquireStatus,
                    processAllRecordings,
                    processBatchRecordings,
                    
                    // Default Prompts methods
                    loadDefaultPrompt,
                    saveDefaultPrompt,
                    resetDefaultPrompt
                };
            },
            delimiters: ['${', '}'] // Use different delimiters to avoid conflict with Flask's Jinja2
        }).mount('#app');

        // Hide loading overlay after Vue is mounted
        Vue.nextTick(() => {
            const overlay = document.querySelector('.app-loading-overlay');
            if (overlay) {
                setTimeout(() => {
                    overlay.classList.add('fade-out');
                    setTimeout(() => {
                        overlay.remove();
                        document.body.classList.remove('app-loading');
                    }, 300);
                }, 100);
            } else {
                document.body.classList.remove('app-loading');
            }
        });
        }); // End of initializeI18n().then()
    </script>
</body>
</html>
