/**
 * Spark Catcher v2.0 - Chrome Extension Popup
 * New tab structure: Add | Sparks | Alerts | Pages
 */

// ============================================
// I18N TRANSLATIONS
// ============================================
const translations = {
    en: {
        spark: "Spark",
        name: "Name",
        description: "Description",
        source: "Source",
        sparkNamePlaceholder: "Spark name...",
        sparkDescPlaceholder: "Description or spark content...",
        sourcePlaceholder: "Source link (optional)",
        delete: "Delete",
        cancel: "Cancel",
        save: "Save",
        add: "Add",
        sparks: "Sparks",
        alerts: "Alerts",
        sites: "Sites",
        ideaBox: "Idea Box",
        note: "Note",
        saveSpark: "Save Spark",
        settings: "Settings",
        logout: "Logout",
        login: "Login with RE::DACT",
        noAccount: "No account?",
        signUpFree: "Sign up free"
    },
    pl: {
        spark: "Iskra",
        name: "Nazwa",
        description: "Opis",
        source: "Źródło",
        sparkNamePlaceholder: "Nazwa iskry...",
        sparkDescPlaceholder: "Opis lub treść iskry...",
        sourcePlaceholder: "Link do źródła (opcjonalnie)",
        delete: "Usuń",
        cancel: "Anuluj",
        save: "Zapisz",
        add: "Dodaj",
        sparks: "Iskry",
        alerts: "Alerty",
        sites: "Strony",
        ideaBox: "Sparks Box",
        note: "Notatka",
        saveSpark: "Zapisz Iskrę",
        settings: "Ustawienia",
        logout: "Wyloguj",
        login: "Zaloguj przez RE::DACT",
        noAccount: "Nie masz konta?",
        signUpFree: "Zarejestruj się"
    }
};

let currentLanguage = navigator.language?.slice(0, 2) || 'en';
if (!translations[currentLanguage]) currentLanguage = 'en';

function t(key) {
    return translations[currentLanguage]?.[key] || translations.en?.[key] || key;
}

function updateUILanguage() {
    document.querySelectorAll('[data-i18n]').forEach(el => {
        el.textContent = t(el.dataset.i18n);
    });
    document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
        el.placeholder = t(el.dataset.i18nPlaceholder);
    });
}

// Apply dark mode from local storage
function applyTheme() {
    if (typeof chrome !== 'undefined' && chrome.storage) {
        chrome.storage.local.get(['sparks_dark_mode'], (result) => {
            if (result.sparks_dark_mode) {
                document.body.classList.add('dark');
                const toggle = document.getElementById('toggle-dark-mode');
                if (toggle) toggle.classList.add('active');
            }
        });
    }
}

// Toggle dark mode
function toggleDarkMode() {
    const isDark = document.body.classList.toggle('dark');
    const toggle = document.getElementById('toggle-dark-mode');
    if (toggle) {
        toggle.classList.toggle('active', isDark);
    }
    if (typeof chrome !== 'undefined' && chrome.storage) {
        chrome.storage.local.set({ sparks_dark_mode: isDark });
    }
}

const API_BASE = 'https://redact-api-vnyj3f4eaq-ew.a.run.app/api';
const APP_URL = 'https://sparks.redact-app.com';

// Page monitoring limits by subscription
const PAGE_LIMITS = {
    sparks: 5,
    freelancer: 10,
    pro: 20,
    enterprise: 30
};

// State
const State = {
    user: null,
    ideaBoxes: [],      // Renamed from topics
    sparks: [],
    alerts: [],
    monitoredPages: [],
    currentSpark: null,
    pageInfo: { title: '', url: '', favicon: '' },
    selectedText: '',
    isPreviewMode: false,
    encryptionEnabled: false,
    encryptionUnlocked: false
};

// DOM helper
const $ = id => document.getElementById(id);

// ============================================
// INITIALIZATION
// ============================================

document.addEventListener('DOMContentLoaded', async () => {
    // Apply theme from Sparks app settings
    applyTheme();

    // Apply translations
    updateUILanguage();

    // Tab switching
    document.querySelectorAll('.tab').forEach(tab => {
        tab.addEventListener('click', () => switchTab(tab.dataset.tab));
    });

    // Toggles (exclude dark mode - has special handler)
    document.querySelectorAll('.toggle:not(#toggle-dark-mode)').forEach(toggle => {
        toggle.addEventListener('click', () => toggle.classList.toggle('active'));
    });

    // Dark mode toggle
    $('toggle-dark-mode')?.addEventListener('click', toggleDarkMode);

    // Buttons
    $('btn-login')?.addEventListener('click', login);
    $('btn-logout')?.addEventListener('click', logout);
    $('btn-save')?.addEventListener('click', saveSpark);
    $('btn-refresh')?.addEventListener('click', refresh);
    $('btn-settings')?.addEventListener('click', openSettingsModal);
    $('btn-add-more')?.addEventListener('click', () => {
        showView('main-view');
        switchTab('add');
    });
    $('btn-open-app')?.addEventListener('click', () => openUrl(APP_URL));
    $('btn-open-garden')?.addEventListener('click', () => openUrl(APP_URL));
    $('btn-update-spark')?.addEventListener('click', updateSpark);
    $('btn-delete-spark')?.addEventListener('click', deleteSpark);
    $('btn-add-page')?.addEventListener('click', addPage);
    $('link-signup')?.addEventListener('click', () => openUrl(APP_URL));

    // Settings modal close handlers
    document.querySelector('#settings-modal .modal-close')?.addEventListener('click', closeSettingsModal);
    document.querySelector('#settings-modal .modal-backdrop')?.addEventListener('click', closeSettingsModal);

    // Encryption modal
    $('btn-unlock-encryption')?.addEventListener('click', openEncryptionModal);
    $('btn-submit-encryption')?.addEventListener('click', submitEncryptionPassword);
    $('encryption-password')?.addEventListener('keypress', e => {
        if (e.key === 'Enter') submitEncryptionPassword();
    });
    document.querySelector('#encryption-modal .modal-close')?.addEventListener('click', closeEncryptionModal);
    document.querySelector('#encryption-modal .modal-backdrop')?.addEventListener('click', closeEncryptionModal);

    // Spark edit modal close handlers
    document.querySelector('#spark-edit-modal .modal-close')?.addEventListener('click', closeSparkEditModal);
    document.querySelector('#spark-edit-modal .modal-backdrop')?.addEventListener('click', closeSparkEditModal);

    // Enter key for add page
    $('new-page-url')?.addEventListener('keypress', e => {
        if (e.key === 'Enter') addPage();
    });

    // Check if running in extension context or browser preview
    // chrome.runtime.id exists only in actual extension context
    const isExtensionContext = typeof chrome !== 'undefined' &&
                               typeof chrome.runtime !== 'undefined' &&
                               typeof chrome.runtime.id !== 'undefined';

    if (isExtensionContext) {
        await checkAuth();

        // Check if we should open a specific tab (e.g., from OPEN_ALERTS message)
        const { sparks_open_tab } = await chrome.storage.local.get('sparks_open_tab');
        if (sparks_open_tab) {
            console.log('[POPUP] Opening requested tab:', sparks_open_tab);
            switchTab(sparks_open_tab);
            // Clear the flag
            await chrome.storage.local.remove('sparks_open_tab');
        }
    } else {
        // Browser preview mode - show UI with demo data
        console.log('Running in preview mode (not extension context)');
        State.isPreviewMode = true;
        enterPreviewMode();
    }
});

// ============================================
// VIEW MANAGEMENT
// ============================================

function showView(viewId) {
    document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
    $(viewId)?.classList.add('active');
}

function switchTab(tabName) {
    document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
    document.querySelector(`[data-tab="${tabName}"]`)?.classList.add('active');

    document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
    $(`tab-${tabName}`)?.classList.add('active');

    // Load data for tabs
    if (tabName === 'add') loadPageInfo();
    if (tabName === 'sparks') loadSparks();
    if (tabName === 'alerts') loadAlerts();
    if (tabName === 'pages') loadMonitoredPages();
}

// ============================================
// MODALS
// ============================================

function openSettingsModal() {
    $('settings-modal').classList.remove('hidden');
    checkAIStatus();  // Check local AI model status
}

window.closeSettingsModal = function() {
    $('settings-modal').classList.add('hidden');
};

// ============================================
// ENCRYPTION MODAL
// ============================================

function openEncryptionModal() {
    $('encryption-modal').classList.remove('hidden');
    $('encryption-password').value = '';
    $('encryption-error').classList.add('hidden');
    $('encryption-password').focus();
}

window.closeEncryptionModal = function() {
    $('encryption-modal').classList.add('hidden');
};

async function submitEncryptionPassword() {
    const password = $('encryption-password').value;
    if (!password) {
        showToast('Enter password', 'error');
        return;
    }

    const errorEl = $('encryption-error');
    errorEl.classList.add('hidden');

    // Get user ID from storage
    const { user_id: userId } = await chrome.storage.local.get('user_id');
    if (!userId) {
        showToast('User not found', 'error');
        return;
    }

    try {
        // Verify password
        const isValid = await SparksCrypto.verifyPassword(password, userId);
        if (isValid) {
            // Initialize encryption
            await SparksCrypto.init(password, userId);
            State.encryptionUnlocked = true;
            updateEncryptionUI();
            closeEncryptionModal();
            showToast('Encryption unlocked', 'success');
            // Reload data to decrypt
            await loadIdeaBoxes();
        } else {
            errorEl.classList.remove('hidden');
            showToast('Wrong password', 'error');
        }
    } catch (e) {
        console.error('[POPUP] Encryption unlock failed:', e);
        errorEl.classList.remove('hidden');
        showToast('Unlock failed: ' + e.message, 'error');
    }
}

async function checkEncryptionStatus() {
    // Check if user has encryption enabled
    if (typeof SparksCrypto === 'undefined') {
        console.log('[POPUP] SparksCrypto not available');
        return;
    }

    State.encryptionEnabled = SparksCrypto.isEnabled();
    State.encryptionUnlocked = SparksCrypto.isReady();
    updateEncryptionUI();

    // If enabled but not unlocked, prompt for password
    if (State.encryptionEnabled && !State.encryptionUnlocked) {
        console.log('[POPUP] Encryption enabled but locked');
    }
}

function updateEncryptionUI() {
    const badge = $('encryption-badge');
    const hint = $('encryption-status-hint');
    const unlockBtn = $('btn-unlock-encryption');

    if (!badge || !hint) return;

    if (typeof SparksCrypto === 'undefined') {
        badge.className = 'encryption-badge inactive';
        badge.textContent = 'N/A';
        hint.textContent = 'Module not loaded';
        if (unlockBtn) unlockBtn.style.display = 'none';
        return;
    }

    if (SparksCrypto.isReady()) {
        badge.className = 'encryption-badge active';
        badge.textContent = 'Active';
        hint.textContent = 'Your data is encrypted';
        if (unlockBtn) unlockBtn.style.display = 'none';
    } else if (SparksCrypto.isEnabled()) {
        badge.className = 'encryption-badge locked';
        badge.textContent = 'Locked';
        hint.textContent = 'Enter password to decrypt';
        if (unlockBtn) unlockBtn.style.display = 'block';
    } else {
        badge.className = 'encryption-badge inactive';
        badge.textContent = 'Off';
        hint.textContent = 'Enable in Sparks App';
        if (unlockBtn) unlockBtn.style.display = 'none';
    }
}

/**
 * Encrypt spark data before saving.
 */
async function encryptSparkData(sparkData) {
    if (typeof SparksCrypto === 'undefined' || !SparksCrypto.isReady()) {
        return sparkData;
    }

    const encrypted = { ...sparkData };
    const fieldsToEncrypt = ['title', 'content', 'content_preview', 'note', 'url'];

    for (const field of fieldsToEncrypt) {
        if (encrypted[field] && typeof encrypted[field] === 'string') {
            encrypted[field] = await SparksCrypto.encrypt(encrypted[field]);
        }
    }

    encrypted._encrypted = true;
    return encrypted;
}

function openSparkEditModal(sparkId) {
    const spark = State.sparks.find(s => s.spark_id === sparkId);
    if (!spark) return;

    State.currentSpark = spark;

    $('edit-name').value = spark.title || spark.name || '';
    $('edit-content').value = spark.content || spark.content_preview || '';
    $('edit-source').value = spark.source_url || '';

    $('spark-edit-modal').classList.remove('hidden');
}

window.closeSparkEditModal = function() {
    $('spark-edit-modal').classList.add('hidden');
    State.currentSpark = null;
};

// ============================================
// AUTH
// ============================================

async function checkAuth() {
    showLoading(true);

    try {
        // Check if we have backend auth token
        const { spark_auth_token: token, spark_user_info: user } = await chrome.storage.local.get(['spark_auth_token', 'spark_user_info']);

        if (token && user) {
            // Verify backend token
            try {
                const response = await fetch(`${API_BASE}/auth/me`, {
                    headers: { 'Authorization': `Bearer ${token}` }
                });

                if (response.ok) {
                    const data = await response.json();
                    if (data.authenticated) {
                        State.user = data.user || user;
                    }
                } else if (response.status === 401) {
                    // Token invalid - clear it
                    console.log('[POPUP] Token invalid (401), clearing...');
                    await chrome.storage.local.remove(['spark_auth_token', 'spark_user_info']);
                }
            } catch (e) {
                console.log('[POPUP] Backend auth check failed, continuing with Drive only');
            }
        }

        // No token and no user - show login
        if (!State.user && !token) {
            console.log('[POPUP] No auth, showing login screen');
            showView('login-view');
            showLoading(false);
            return;
        }

        // Check encryption status
        await checkEncryptionStatus();

        // Load Sparks Boxes
        await loadIdeaBoxes();
        await loadPageInfo();
        updateUserUI();
        updateEncryptionUI();

        // If we have Sparks Boxes, show main view
        if (State.ideaBoxes.length > 0) {
            showView('main-view');
        } else {
            console.log('[POPUP] No Sparks Boxes found.');
            showView('main-view');
            showToast('No Sparks Boxes found. Create one in RE::DACT Sparks first.', 'info');
        }

    } catch (e) {
        console.error('Auth check failed:', e);
        showView('login-view');
    }

    showLoading(false);
}

async function login() {
    console.log('[POPUP] Starting login...');
    showLoading(true);

    try {
        // Open Sparks app for login - Token Bridge will send token back to extension
        await chrome.runtime.sendMessage({ action: 'login' });
        // Popup closes when user navigates to Sparks app tab
        // On next popup open, checkAuth() will find the token from Token Bridge
        showToast('Sign in on the Sparks page that opened', 'info');
    } catch (error) {
        console.error('[POPUP] Login error:', error);
        showToast('Login error: ' + error.message, 'error');
    } finally {
        showLoading(false);
    }
}

async function logout() {
    // Tell background to clear all auth state
    await chrome.runtime.sendMessage({ action: 'logout' });
    // Clear local state
    State.user = null;
    State.ideaBoxes = [];
    State.sparks = [];
    State.alerts = [];
    State.monitoredPages = [];
    closeSettingsModal();
    showView('login-view');
    showToast('Logged out', 'success');
}

function updateUserUI() {
    if (State.user) {
        $('user-email-footer').textContent = State.user.email || '';
        $('settings-email').textContent = State.user.email || '';
    }
}

// ============================================
// DATA LOADING
// ============================================

/**
 * Get Google Drive token using Chrome Identity API.
 * Extension authorizes directly with Google - no need for Sparks App.
 */
async function getDriveToken() {
    return new Promise((resolve, reject) => {
        // First check if we have a cached token
        chrome.storage.local.get('sparks_drive_token', (result) => {
            if (result.sparks_drive_token) {
                console.log('[POPUP] Using cached Drive token');
                resolve(result.sparks_drive_token);
                return;
            }

            // Request new token via Chrome Identity API
            console.log('[POPUP] Requesting Drive token via Chrome Identity...');
            chrome.identity.getAuthToken({ interactive: true }, (token) => {
                if (chrome.runtime.lastError) {
                    console.error('[POPUP] Identity error:', chrome.runtime.lastError.message);
                    reject(chrome.runtime.lastError);
                    return;
                }

                if (token) {
                    console.log('[POPUP] ✅ Got Drive token from Chrome Identity');
                    // Cache the token
                    chrome.storage.local.set({ 'sparks_drive_token': token });
                    resolve(token);
                } else {
                    reject(new Error('No token received'));
                }
            });
        });
    });
}

/**
 * Clear cached Drive token and get a new one
 */
async function refreshDriveToken() {
    return new Promise((resolve, reject) => {
        chrome.identity.getAuthToken({ interactive: false }, (currentToken) => {
            if (currentToken) {
                // Remove the cached token
                chrome.identity.removeCachedAuthToken({ token: currentToken }, () => {
                    // Get a new one
                    chrome.identity.getAuthToken({ interactive: true }, (newToken) => {
                        if (newToken) {
                            chrome.storage.local.set({ 'sparks_drive_token': newToken });
                            resolve(newToken);
                        } else {
                            reject(new Error('Failed to refresh token'));
                        }
                    });
                });
            } else {
                // No current token, just get a new one
                chrome.identity.getAuthToken({ interactive: true }, (token) => {
                    if (token) {
                        chrome.storage.local.set({ 'sparks_drive_token': token });
                        resolve(token);
                    } else {
                        reject(new Error('Failed to get token'));
                    }
                });
            }
        });
    });
}

async function loadIdeaBoxes() {
    if (State.isPreviewMode) {
        renderIdeaBoxSelect();
        return;
    }

    console.log('[POPUP] Loading Sparks Boxes...');

    try {
        // PRIMARY: Try unified Storage API (Firestore-backed)
        // This is the single source of truth - no race conditions
        console.log('[POPUP] Trying Storage API (primary)...');
        const storageSuccess = await loadIdeaBoxesFromStorageAPI();
        if (storageSuccess) {
            console.log('[POPUP] Loaded from Storage API');
            return;
        }

        // FALLBACK 1: Try Google Drive (legacy)
        let driveToken;
        try {
            driveToken = await getDriveToken();
            console.log('[POPUP] Got Drive token:', driveToken ? 'YES' : 'NO');
        } catch (e) {
            console.log('[POPUP] Could not get Drive token:', e.message);
        }

        if (driveToken) {
            console.log('[POPUP] Have Drive token, loading from Drive (fallback)...');
            const success = await loadIdeaBoxesFromDrive(driveToken);
            console.log('[POPUP] Drive load result:', success);
            if (success) return;

            // Token might be expired, try refresh
            console.log('[POPUP] Drive load failed, trying token refresh...');
            try {
                driveToken = await refreshDriveToken();
                const retrySuccess = await loadIdeaBoxesFromDrive(driveToken);
                if (retrySuccess) return;
            } catch (e) {
                console.log('[POPUP] Token refresh failed:', e.message);
            }
        }

        // FALLBACK 2: Try local cache
        console.log('[POPUP] Storage API and Drive unavailable, checking cache...');
        const { spark_projects_cache: cachedSparks } = await chrome.storage.local.get('spark_projects_cache');
        if (cachedSparks && cachedSparks.length > 0) {
            console.log('[POPUP] Using cached sparks:', cachedSparks.length);
            State.ideaBoxes = cachedSparks;
            renderIdeaBoxSelect();
            return;
        }

        // LAST RESORT: Legacy API call
        console.log('[POPUP] No Storage API/Drive/cache, trying legacy API...');
        await loadIdeaBoxesFromAPI();

    } catch (e) {
        console.error('[POPUP] Failed to load Sparks Boxes:', e);
    }
}

/**
 * Load Sparks Boxes directly from Google Drive.
 * Uses same data structure as Sparks App (sparks_index.json + sparks_project_*.json)
 */
async function loadIdeaBoxesFromDrive(driveToken) {
    try {
        console.log('[POPUP] Reading from Google Drive...');

        // 1. Find RE_DACT folder
        const folderResp = await fetch(
            `https://www.googleapis.com/drive/v3/files?q=name='RE_DACT' and mimeType='application/vnd.google-apps.folder' and trashed=false&fields=files(id,name)`,
            { headers: { 'Authorization': `Bearer ${driveToken}` } }
        );

        if (!folderResp.ok) {
            console.error('[POPUP] Drive folder search failed:', folderResp.status);
            return false;
        }

        const folderData = await folderResp.json();
        const folderId = folderData.files?.[0]?.id;

        if (!folderId) {
            console.log('[POPUP] RE_DACT folder not found on Drive - clearing cache');
            // No folder = no sparks, clear cache
            State.ideaBoxes = [];
            await chrome.storage.local.remove('spark_projects_cache');
            renderIdeaBoxSelect();
            return true; // Successfully checked Drive, it's just empty
        }

        // 2. Find sparks_index.json
        const indexResp = await fetch(
            `https://www.googleapis.com/drive/v3/files?q=name='sparks_index.json' and '${folderId}' in parents and trashed=false&fields=files(id,name)`,
            { headers: { 'Authorization': `Bearer ${driveToken}` } }
        );

        if (!indexResp.ok) {
            console.error('[POPUP] Drive index search failed:', indexResp.status);
            return false;
        }

        const indexData = await indexResp.json();
        const indexFileId = indexData.files?.[0]?.id;

        if (!indexFileId) {
            console.log('[POPUP] sparks_index.json not found - Drive is empty');
            // Drive folder exists but no sparks - clear cache and show empty
            State.ideaBoxes = [];
            await chrome.storage.local.remove('spark_projects_cache');
            renderIdeaBoxSelect();
            return true; // We successfully checked Drive, it's just empty
        }

        // 3. Download sparks_index.json
        const contentResp = await fetch(
            `https://www.googleapis.com/drive/v3/files/${indexFileId}?alt=media`,
            { headers: { 'Authorization': `Bearer ${driveToken}` } }
        );

        if (!contentResp.ok) {
            console.error('[POPUP] Drive download failed:', contentResp.status);
            return false;
        }

        const indexContent = await contentResp.json();
        console.log('[POPUP] Index loaded:', indexContent);

        // Check if index has no topics (Drive was cleared)
        if (!indexContent.topics || indexContent.topics.length === 0) {
            console.log('[POPUP] Drive index is empty - no sparks');
            State.ideaBoxes = [];
            await chrome.storage.local.remove('spark_projects_cache');
            renderIdeaBoxSelect();
            return true;
        }

        // 4. Load full topic data from sparks_project_*.json files
        const ideaBoxes = [];

        for (const topicMeta of (indexContent.topics || [])) {
            // Find the project file
            const projectFileName = `sparks_project_${topicMeta.topicId}.json`;
            const projectResp = await fetch(
                `https://www.googleapis.com/drive/v3/files?q=name='${projectFileName}' and '${folderId}' in parents and trashed=false&fields=files(id,name)`,
                { headers: { 'Authorization': `Bearer ${driveToken}` } }
            );

            if (projectResp.ok) {
                const projectData = await projectResp.json();
                const projectFileId = projectData.files?.[0]?.id;

                if (projectFileId) {
                    // Download project file to get full topic data (with color, icon, etc.)
                    const projectContentResp = await fetch(
                        `https://www.googleapis.com/drive/v3/files/${projectFileId}?alt=media`,
                        { headers: { 'Authorization': `Bearer ${driveToken}` } }
                    );

                    if (projectContentResp.ok) {
                        const projectContent = await projectContentResp.json();

                        if (projectContent.topic) {
                            // Use full topic data from project file
                            ideaBoxes.push({
                                topic_id: projectContent.topic.topic_id || topicMeta.topicId,
                                title: projectContent.topic.title || topicMeta.title,
                                description: projectContent.topic.description || '',
                                color: projectContent.topic.color || '#FF9A00',
                                icon: projectContent.topic.icon || '⚡',
                                sparksCount: (projectContent.sparks || []).length,
                                // Keep reference to Drive data
                                _driveId: topicMeta.driveId,
                                _projectFileId: projectFileId,
                            });
                        }
                    }
                }
            }

            // Skip topics where project file doesn't exist (orphaned index entries)
            // Don't add "ghost" topics from index - only show topics with actual files
        }

        State.ideaBoxes = ideaBoxes;
        console.log('[POPUP] ✅ Loaded from Drive:', State.ideaBoxes.length, 'Sparks Boxes');

        // CLEANUP: Remove orphaned entries from index if any were found
        const loadedTopicIds = ideaBoxes.map(b => b.topic_id);
        const orphanedTopics = indexContent.topics.filter(t => !loadedTopicIds.includes(t.topicId));

        if (orphanedTopics.length > 0) {
            console.log('[POPUP] 🧹 Cleaning up', orphanedTopics.length, 'orphaned index entries...');

            // Update index with only valid topics
            const cleanedIndex = {
                ...indexContent,
                topics: indexContent.topics.filter(t => loadedTopicIds.includes(t.topicId)),
                lastCleanup: new Date().toISOString()
            };

            // Save cleaned index back to Drive
            try {
                await fetch(`https://www.googleapis.com/upload/drive/v3/files/${indexFileId}?uploadType=media`, {
                    method: 'PATCH',
                    headers: {
                        'Authorization': `Bearer ${driveToken}`,
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(cleanedIndex, null, 2)
                });
                console.log('[POPUP] ✅ Index cleaned up on Drive');
            } catch (cleanupErr) {
                console.warn('[POPUP] Could not update index:', cleanupErr);
            }
        }

        // Update cache with fresh Drive data
        await chrome.storage.local.set({ 'spark_projects_cache': ideaBoxes });

        renderIdeaBoxSelect();
        return true;

    } catch (e) {
        console.error('[POPUP] Drive read error:', e);
        return false;
    }
}

/**
 * PRIMARY: Load from unified Storage API (Firestore-backed)
 * This is the single source of truth for Sparks data.
 */
async function loadIdeaBoxesFromStorageAPI() {
    try {
        const { spark_auth_token: token, user_id: userId } = await chrome.storage.local.get(['spark_auth_token', 'user_id']);

        const params = new URLSearchParams();
        if (userId) params.set('user_id', userId);

        const response = await fetch(`${API_BASE}/storage/projects?${params}`, {
            headers: token ? { 'Authorization': `Bearer ${token}` } : {}
        });

        if (response.ok) {
            const data = await response.json();
            if (data.success) {
                // Normalize: add topic_id from project_id for backward compatibility
                State.ideaBoxes = (data.projects || []).map(p => ({
                    ...p,
                    topic_id: p.project_id || p.topic_id,
                    project_id: p.project_id || p.topic_id
                }));
                console.log('[POPUP] Loaded from Storage API:', State.ideaBoxes.length);
                // Cache for offline use
                await chrome.storage.local.set({ spark_projects_cache: State.ideaBoxes });
                renderIdeaBoxSelect();
                return true;
            }
        }

        console.error('[POPUP] Storage API error:', response.status);
        return false;
    } catch (e) {
        console.error('[POPUP] Storage API failed:', e);
        return false;
    }
}

/**
 * Save spark via unified Storage API (Firestore-backed)
 */
async function saveSparkToStorageAPI(topicId, sparkData) {
    try {
        const { spark_auth_token: token, user_id: userId } = await chrome.storage.local.get(['spark_auth_token', 'user_id']);

        const params = new URLSearchParams();
        if (userId) params.set('user_id', userId);

        // Prepare spark data - API expects project_id
        let dataToSend = {
            project_id: topicId,  // API uses project_id
            title: sparkData.title || 'Untitled',
            content_preview: sparkData.content || '',  // Full content, no truncation
            source_type: sparkData.sourceType || 'snippet',
            url: sparkData.sourceUrl || '',
            note: sparkData.note || ''
        };

        // Encrypt if encryption is enabled
        if (typeof SparksCrypto !== 'undefined' && SparksCrypto.isReady()) {
            console.log('[POPUP] Encrypting spark data before save...');
            dataToSend = await encryptSparkData(dataToSend);
        }

        const response = await fetch(`${API_BASE}/storage/sparks?${params}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                ...(token ? { 'Authorization': `Bearer ${token}` } : {})
            },
            body: JSON.stringify(dataToSend)
        });

        if (response.ok) {
            const data = await response.json();
            if (data.success) {
                console.log('[POPUP] Spark saved via Storage API:', data.spark?.spark_id);
                return true;
            }
        }

        console.error('[POPUP] Storage API save failed:', response.status);
        return false;
    } catch (e) {
        console.error('[POPUP] Storage API save error:', e);
        return false;
    }
}

/**
 * Fallback: Load from legacy backend API
 */
async function loadIdeaBoxesFromAPI() {
    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        if (!token) {
            console.log('[POPUP] No API token');
            return;
        }

        const response = await fetch(`${API_BASE}/sparks/topics`, {
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (response.ok) {
            const data = await response.json();
            State.ideaBoxes = data.topics || data || [];
            console.log('[POPUP] Loaded from legacy API:', State.ideaBoxes.length);
            renderIdeaBoxSelect();
        } else {
            console.error('[POPUP] Legacy API error:', response.status);
        }
    } catch (e) {
        console.error('[POPUP] Legacy API fallback failed:', e);
    }
}

async function loadSparks() {
    if (State.isPreviewMode) {
        renderSparksList();
        return;
    }

    const list = $('sparks-list');
    list.innerHTML = '<div class="empty-state"><div class="spinner"></div></div>';

    try {
        const { spark_auth_token: token, user_id: userId } = await chrome.storage.local.get(['spark_auth_token', 'user_id']);

        let allSparks = [];
        for (const box of State.ideaBoxes.slice(0, 5)) {
            const projectId = box.project_id || box.topic_id;
            const params = new URLSearchParams();
            if (userId) params.set('user_id', userId);
            params.set('project_id', projectId);
            params.set('limit', '10');

            const response = await fetch(`${API_BASE}/storage/sparks?${params}`, {
                headers: token ? { 'Authorization': `Bearer ${token}` } : {}
            });
            if (response.ok) {
                const data = await response.json();
                const sparks = (data.sparks || []).map(s => ({
                    ...s,
                    topic_title: box.title,
                    topic_color: box.color
                }));
                allSparks = allSparks.concat(sparks);
            }
        }

        allSparks.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
        State.sparks = allSparks.slice(0, 20);

        renderSparksList();
        $('sparks-count').textContent = `${State.sparks.length} sparks`;
    } catch (e) {
        console.error('Failed to load sparks:', e);
        list.innerHTML = '<div class="empty-state"><p>Failed to load</p></div>';
    }
}

async function loadAlerts() {
    if (State.isPreviewMode) {
        renderAlertsList();
        updateAlertsBadge();
        return;
    }

    const list = $('alerts-list');
    list.innerHTML = '<div class="empty-state"><div class="spinner"></div></div>';

    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        const response = await fetch(`${API_BASE}/sparks/alerts`, {
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (response.ok) {
            const data = await response.json();
            State.alerts = data.alerts || [];
            renderAlertsList();
            updateAlertsBadge();
        } else {
            // API might not exist yet - show empty state
            State.alerts = [];
            renderAlertsList();
        }
    } catch (e) {
        console.error('Failed to load alerts:', e);
        State.alerts = [];
        renderAlertsList();
    }
}

async function loadMonitoredPages() {
    if (State.isPreviewMode) {
        renderPagesList();
        return;
    }

    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        const response = await fetch(`${API_BASE}/sparks/monitored-pages`, {
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (response.ok) {
            const data = await response.json();
            State.monitoredPages = data.pages || [];
        } else {
            State.monitoredPages = [];
        }
        renderPagesList();
    } catch (e) {
        console.error('Failed to load monitored pages:', e);
        State.monitoredPages = [];
        renderPagesList();
    }
}

async function loadPageInfo() {
    if (State.isPreviewMode) {
        return; // Use demo data
    }

    try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        if (tab) {
            State.pageInfo = {
                title: tab.title || 'Unknown page',
                url: tab.url || '',
                favicon: tab.favIconUrl || ''
            };

            $('page-title').textContent = State.pageInfo.title;
            $('page-url').textContent = State.pageInfo.url;
            $('source-url').value = State.pageInfo.url;

            const faviconEl = $('page-favicon');
            if (State.pageInfo.favicon) {
                faviconEl.innerHTML = `<img src="${State.pageInfo.favicon}" alt="">`;
            }
        }

        // Get selected text
        const [result] = await chrome.scripting.executeScript({
            target: { tabId: tab.id },
            func: () => window.getSelection().toString()
        });

        if (result?.result) {
            State.selectedText = result.result.trim();
            if (State.selectedText) {
                $('selection-preview').classList.remove('hidden');
                $('selection-text').textContent = State.selectedText.substring(0, 500);
            } else {
                $('selection-preview').classList.add('hidden');
            }
        }
    } catch (e) {
        console.error('Failed to get page info:', e);
    }
}

// ============================================
// RENDERING
// ============================================

function renderIdeaBoxSelect() {
    const select = $('idea-box-select');
    // Limit to 10 most recent, sorted by updated_at or title
    const sortedBoxes = [...State.ideaBoxes]
        .sort((a, b) => (b.updated_at || '').localeCompare(a.updated_at || ''))
        .slice(0, 10);
    const hasMore = State.ideaBoxes.length > 10;

    const truncate = (str, len = 28) => str.length > len ? str.slice(0, len) + '...' : str;
    select.innerHTML = '<option value="">Select Idea Box...</option>' +
        sortedBoxes.map(box => `<option value="${box.topic_id || box.project_id}">${escapeHtml(truncate(box.title))}</option>`).join('') +
        (hasMore ? `<option disabled>── ${State.ideaBoxes.length - 10} more ──</option>` : '');
}

function renderSparksList() {
    const list = $('sparks-list');

    if (State.sparks.length === 0) {
        list.innerHTML = `
            <div class="empty-state">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
                <p>No sparks yet</p>
            </div>
        `;
        return;
    }

    list.innerHTML = State.sparks.map(spark => {
        const color = spark.topic_color || '#FF9A00';
        return `
        <div class="spark-item" onclick="openSparkEditModal('${spark.spark_id}')">
            <div class="spark-item-header">
                <span class="spark-topic-badge" style="background:${color}20;color:${color}">
                    ${escapeHtml(spark.topic_title || 'Idea Box')}
                </span>
                <span class="spark-date">${formatDate(spark.created_at)}</span>
            </div>
            <div class="spark-content">${escapeHtml(spark.content_preview || spark.content || '')}</div>
            ${spark.source_url ? `<div class="spark-source"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg><span>${escapeHtml(new URL(spark.source_url).hostname)}</span></div>` : ''}
        </div>
        `;
    }).join('');
}

function renderAlertsList() {
    const list = $('alerts-list');

    if (!State.alerts.length) {
        list.innerHTML = `
            <div class="empty-state">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
                    <path d="M9 18h6"/><path d="M10 22h4"/>
                    <path d="M12 2a7 7 0 0 0-7 7c0 2.38 1.19 4.47 3 5.74V17a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-2.26c1.81-1.27 3-3.36 3-5.74a7 7 0 0 0-7-7z"/>
                </svg>
                <p>No alerts yet</p>
                <p class="hint">Alerts appear when pages match your Idea Boxes</p>
            </div>
        `;
        return;
    }

    list.innerHTML = State.alerts.map(alert => {
        const bulbs = renderStrengthBulbs(alert.strength || 1);
        const isAuto = alert.source === 'auto';

        return `
        <div class="alert-item" onclick="openAlertPage('${escapeHtml(alert.page_url)}')">
            ${isAuto ? `
                <div class="alert-ai-badge" title="Auto-discovered">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <rect x="3" y="11" width="18" height="10" rx="2"/>
                        <circle cx="12" cy="5" r="3"/>
                    </svg>
                </div>
            ` : ''}
            <div class="alert-header">
                ${bulbs}
                <span class="alert-idea-box">${escapeHtml(alert.idea_box_name || 'Idea Box')}</span>
            </div>
            <div class="alert-title">${escapeHtml(alert.page_title || 'Page')}</div>
            <div class="alert-source">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
                </svg>
                <span>${escapeHtml(alert.page_url ? new URL(alert.page_url).hostname : '')}</span>
            </div>
        </div>
        `;
    }).join('');
}

function renderStrengthBulbs(strength) {
    const bulbSvg = (active) => `
        <svg class="alert-bulb ${active ? 'active' : ''}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M9 18h6"/><path d="M10 22h4"/>
            <path d="M12 2a7 7 0 0 0-7 7c0 2.38 1.19 4.47 3 5.74V17a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-2.26c1.81-1.27 3-3.36 3-5.74a7 7 0 0 0-7-7z"/>
        </svg>
    `;

    return `<div class="alert-strength">
        ${bulbSvg(strength >= 1)}
        ${bulbSvg(strength >= 2)}
        ${bulbSvg(strength >= 3)}
    </div>`;
}

function renderPagesList() {
    const list = $('pages-list');
    const limit = PAGE_LIMITS[State.user?.subscription || 'sparks'];

    $('pages-count').textContent = State.monitoredPages.length;

    if (!State.monitoredPages.length) {
        list.innerHTML = `
            <div class="empty-state" style="height:150px">
                <p>No monitored pages</p>
                <p class="hint">Add URLs to monitor for relevant content</p>
            </div>
        `;
        return;
    }

    list.innerHTML = State.monitoredPages.map(page => {
        const statusClass = page.status === 'ok' ? 'ok' :
                           page.status === 'error' ? 'error' : 'pending';
        const lastCheck = page.last_checked ? formatDate(page.last_checked) : 'Not checked';

        return `
        <div class="page-monitor-item">
            <div class="page-status ${statusClass}" title="${page.status_message || page.status}"></div>
            <div class="page-monitor-url" title="${escapeHtml(page.url)}">${escapeHtml(new URL(page.url).hostname)}</div>
            <div class="page-last-check">${lastCheck}</div>
            <button class="page-remove" onclick="removePage('${page.id}')" title="Remove">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
                </svg>
            </button>
        </div>
        `;
    }).join('');
}

function updateAlertsBadge() {
    const badge = $('alerts-badge');
    const count = State.alerts.length;

    if (count > 0) {
        badge.textContent = count > 99 ? '99+' : count;
        badge.classList.remove('hidden');
    } else {
        badge.classList.add('hidden');
    }
}

// ============================================
// ACTIONS
// ============================================

async function saveSpark() {
    const ideaBoxId = $('idea-box-select').value;
    const note = $('note-input').value.trim();
    const sourceUrl = $('source-url')?.value?.trim() || State.pageInfo.url;

    if (!ideaBoxId) {
        showToast('Select a Sparks Box', 'error');
        return;
    }

    const content = State.selectedText || State.pageInfo.title;
    if (!content) {
        showToast('No content to save', 'error');
        return;
    }

    showLoading(true);

    try {
        // PRIMARY: Try unified Storage API (Firestore-backed)
        // This is the single source of truth - no race conditions
        console.log('[POPUP] Saving spark via Storage API (primary)...');
        const storageSuccess = await saveSparkToStorageAPI(ideaBoxId, {
            content,
            note,
            sourceUrl,
            sourceType: State.selectedText ? 'snippet' : 'url',
            title: State.pageInfo?.title || '',
        });

        if (storageSuccess) {
            const ideaBox = State.ideaBoxes.find(b => b.topic_id === ideaBoxId);
            $('success-topic').textContent = `Added to: ${ideaBox?.title || 'Sparks Box'}`;
            showView('success-view');

            // Clear form
            $('note-input').value = '';
            State.selectedText = '';
            $('selection-preview').classList.add('hidden');
            showLoading(false);
            return;
        }

        // FALLBACK 1: Try Google Drive (legacy)
        const { sparks_drive_token: driveToken } = await chrome.storage.local.get('sparks_drive_token');

        if (driveToken) {
            console.log('[POPUP] Trying Drive save (fallback)...');
            const success = await saveSparkToDrive(driveToken, ideaBoxId, {
                content,
                note,
                sourceUrl,
                title: State.pageInfo?.title || '',
            });

            if (success) {
                const ideaBox = State.ideaBoxes.find(b => b.topic_id === ideaBoxId);
                $('success-topic').textContent = `Added to: ${ideaBox?.title || 'Sparks Box'}`;
                showView('success-view');

                // Clear form
                $('note-input').value = '';
                State.selectedText = '';
                $('selection-preview').classList.add('hidden');
                showLoading(false);
                return;
            }
        }

        // FALLBACK 2: Legacy API
        console.log('[POPUP] Trying legacy API save (fallback)...');
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');

        const response = await fetch(`${API_BASE}/sparks/`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify({
                topic_id: ideaBoxId,
                title: State.pageInfo?.title || 'Untitled',
                content: content,
                content_preview: content,  // Full content, no truncation
                url: sourceUrl,
                source_type: State.selectedText ? 'snippet' : 'url',
                note: note,
            })
        });

        if (response.ok) {
            const ideaBox = State.ideaBoxes.find(b => b.topic_id === ideaBoxId);
            $('success-topic').textContent = `Added to: ${ideaBox?.title || 'Sparks Box'}`;
            showView('success-view');

            // Clear form
            $('note-input').value = '';
            State.selectedText = '';
            $('selection-preview').classList.add('hidden');
        } else {
            const err = await response.json();
            throw new Error(err.detail || 'Save failed');
        }
    } catch (e) {
        showToast('Error: ' + e.message, 'error');
    }

    showLoading(false);
}

/**
 * Save spark directly to Google Drive (same format as Sparks App)
 */
async function saveSparkToDrive(driveToken, topicId, sparkData) {
    try {
        console.log('[POPUP] Saving spark to Drive...');

        // Find the ideaBox to get _projectFileId
        const ideaBox = State.ideaBoxes.find(b => b.topic_id === topicId);
        if (!ideaBox || !ideaBox._projectFileId) {
            console.log('[POPUP] No project file ID, cannot save to Drive');
            return false;
        }

        // 1. Download current project file
        const projectResp = await fetch(
            `https://www.googleapis.com/drive/v3/files/${ideaBox._projectFileId}?alt=media`,
            { headers: { 'Authorization': `Bearer ${driveToken}` } }
        );

        if (!projectResp.ok) {
            console.error('[POPUP] Failed to download project file');
            return false;
        }

        const projectContent = await projectResp.json();

        // 2. Add new spark
        const newSpark = {
            spark_id: `spark_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            topic_id: topicId,
            title: sparkData.title || 'Untitled',
            content: sparkData.content,
            content_preview: sparkData.content,  // Full content, no truncation
            source_url: sparkData.sourceUrl || '',
            source_type: 'article',
            note: sparkData.note || '',
            created_at: new Date().toISOString(),
            cloudSavedAt: new Date().toISOString(),
        };

        projectContent.sparks = projectContent.sparks || [];
        projectContent.sparks.push(newSpark);
        projectContent.topic.cloudSavedAt = new Date().toISOString();

        // 3. Upload updated project file
        const updateResp = await fetch(
            `https://www.googleapis.com/upload/drive/v3/files/${ideaBox._projectFileId}?uploadType=media`,
            {
                method: 'PATCH',
                headers: {
                    'Authorization': `Bearer ${driveToken}`,
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(projectContent, null, 2),
            }
        );

        if (!updateResp.ok) {
            console.error('[POPUP] Failed to update project file:', updateResp.status);
            return false;
        }

        // 4. Update index (sparksCount)
        // Find RE_DACT folder first
        const folderResp = await fetch(
            `https://www.googleapis.com/drive/v3/files?q=name='RE_DACT' and mimeType='application/vnd.google-apps.folder' and trashed=false&fields=files(id)`,
            { headers: { 'Authorization': `Bearer ${driveToken}` } }
        );
        const folderData = await folderResp.json();
        const folderId = folderData.files?.[0]?.id;

        if (folderId) {
            // Find index file
            const indexSearchResp = await fetch(
                `https://www.googleapis.com/drive/v3/files?q=name='sparks_index.json' and '${folderId}' in parents and trashed=false&fields=files(id)`,
                { headers: { 'Authorization': `Bearer ${driveToken}` } }
            );
            const indexSearchData = await indexSearchResp.json();
            const indexFileId = indexSearchData.files?.[0]?.id;

            if (indexFileId) {
                // Download index
                const indexResp = await fetch(
                    `https://www.googleapis.com/drive/v3/files/${indexFileId}?alt=media`,
                    { headers: { 'Authorization': `Bearer ${driveToken}` } }
                );
                const indexContent = await indexResp.json();

                // Update sparksCount
                const topicIdx = indexContent.topics.findIndex(t => t.topicId === topicId);
                if (topicIdx >= 0) {
                    indexContent.topics[topicIdx].sparksCount = projectContent.sparks.length;
                    indexContent.topics[topicIdx].updated = new Date().toISOString();
                    indexContent.lastSync = new Date().toISOString();

                    // Upload updated index
                    await fetch(
                        `https://www.googleapis.com/upload/drive/v3/files/${indexFileId}?uploadType=media`,
                        {
                            method: 'PATCH',
                            headers: {
                                'Authorization': `Bearer ${driveToken}`,
                                'Content-Type': 'application/json',
                            },
                            body: JSON.stringify(indexContent, null, 2),
                        }
                    );
                }
            }
        }

        console.log('[POPUP] ✅ Spark saved to Drive');
        return true;

    } catch (e) {
        console.error('[POPUP] Drive save error:', e);
        return false;
    }
}

async function updateSpark() {
    if (!State.currentSpark) return;

    if (State.isPreviewMode) {
        showToast('Zapisano (preview)', 'success');
        closeSparkEditModal();
        return;
    }

    showLoading(true);

    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        const response = await fetch(`${API_BASE}/sparks/${State.currentSpark.spark_id}`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify({
                title: $('edit-name').value,
                content: $('edit-content').value,
                source_url: $('edit-source').value
            })
        });

        if (response.ok) {
            showToast('Changes saved', 'success');
            closeSparkEditModal();
            await loadSparks();
        } else {
            throw new Error('Update failed');
        }
    } catch (e) {
        showToast('Error: ' + e.message, 'error');
    }

    showLoading(false);
}

async function deleteSpark() {
    if (!State.currentSpark) return;
    if (!confirm('Delete this spark?')) return;

    showLoading(true);

    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        const response = await fetch(`${API_BASE}/sparks/${State.currentSpark.spark_id}`, {
            method: 'DELETE',
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (response.ok) {
            showToast('Deleted', 'success');
            closeSparkEditModal();
            await loadSparks();
        } else {
            throw new Error('Delete failed');
        }
    } catch (e) {
        showToast('Error: ' + e.message, 'error');
    }

    showLoading(false);
}

async function addPage() {
    const url = $('new-page-url').value.trim();
    if (!url) return;

    // Validate URL
    try {
        new URL(url);
    } catch {
        showToast('Invalid URL', 'error');
        return;
    }

    // Check limit
    const limit = PAGE_LIMITS[State.user?.subscription || 'sparks'];
    if (State.monitoredPages.length >= limit) {
        showToast(`Limit reached (${limit} pages). Upgrade for more.`, 'error');
        return;
    }

    showLoading(true);

    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        const response = await fetch(`${API_BASE}/sparks/monitored-pages`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            body: JSON.stringify({ url })
        });

        if (response.ok) {
            const page = await response.json();
            State.monitoredPages.push(page);
            renderPagesList();
            $('new-page-url').value = '';
            showToast('Page added', 'success');
        } else {
            const err = await response.json();
            throw new Error(err.detail || 'Failed to add page');
        }
    } catch (e) {
        showToast('Error: ' + e.message, 'error');
    }

    showLoading(false);
}

window.removePage = async function(pageId) {
    if (!confirm('Remove this page?')) return;

    try {
        const { spark_auth_token: token } = await chrome.storage.local.get('spark_auth_token');
        await fetch(`${API_BASE}/sparks/monitored-pages/${pageId}`, {
            method: 'DELETE',
            headers: { 'Authorization': `Bearer ${token}` }
        });

        State.monitoredPages = State.monitoredPages.filter(p => p.id !== pageId);
        renderPagesList();
        showToast('Page removed', 'success');
    } catch (e) {
        showToast('Error removing page', 'error');
    }
};

window.openAlertPage = function(url) {
    chrome.tabs.create({ url });
};

async function refresh() {
    // Clear cache before refresh to force reload from Drive
    console.log('[POPUP] Refresh - clearing cache first...');
    await chrome.storage.local.remove('spark_projects_cache');

    await loadIdeaBoxes();
    await loadSparks();
    await loadAlerts();
    await loadPageInfo();
    showToast('Refreshed', 'success');
}

// Debug function - call from console: clearAllCache()
window.clearAllCache = async function() {
    console.log('[POPUP] Clearing ALL extension cache...');
    await chrome.storage.local.remove([
        'spark_projects_cache',
        'sparks_drive_token',
        'spark_auth_token',
        'spark_user_info'
    ]);
    State.ideaBoxes = [];
    State.sparks = [];
    State.user = null;
    renderIdeaBoxSelect();
    showToast('Cache cleared! Reload extension.', 'success');
    console.log('[POPUP] ✅ All cache cleared');
};

// ============================================
// HELPERS
// ============================================

function openUrl(url) {
    if (typeof chrome !== 'undefined' && chrome.tabs) {
        chrome.tabs.create({ url });
    } else {
        window.open(url, '_blank');
    }
}

function showLoading(show) {
    $('loading').classList.toggle('hidden', !show);
}

function showToast(message, type = 'info') {
    const toast = $('toast');
    toast.textContent = message;
    toast.className = `toast ${type}`;
    toast.classList.remove('hidden');
    setTimeout(() => toast.classList.add('hidden'), 3000);
}

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

function formatDate(dateStr) {
    if (!dateStr) return '';
    const date = new Date(dateStr);
    const now = new Date();
    const diff = now - date;

    if (diff < 60000) return 'now';
    if (diff < 3600000) return `${Math.floor(diff / 60000)}m`;
    if (diff < 86400000) return `${Math.floor(diff / 3600000)}h`;
    if (diff < 604800000) return `${Math.floor(diff / 86400000)}d`;

    return date.toLocaleDateString('en-US', { day: 'numeric', month: 'short' });
}

// Global functions for onclick handlers
window.openSparkEditModal = openSparkEditModal;

// ============================================
// PREVIEW MODE (for testing UI outside extension)
// ============================================

function enterPreviewMode() {
    // Demo user
    State.user = { email: 'preview@demo.com', subscription: 'pro' };

    // Demo Idea Boxes
    State.ideaBoxes = [
        { topic_id: 'ib1', title: 'AI Research', color: '#FF9A00' },
        { topic_id: 'ib2', title: 'Climate Tech', color: '#22C55E' },
        { topic_id: 'ib3', title: 'Web3 Trends', color: '#8B5CF6' }
    ];

    // Demo sparks
    State.sparks = [
        {
            spark_id: 's1',
            title: 'GPT-5 Breakthrough',
            content_preview: 'GPT-5 reportedly achieving human-level reasoning on complex tasks...',
            content: 'GPT-5 reportedly achieving human-level reasoning on complex tasks. The model shows unprecedented ability to solve multi-step problems.',
            topic_title: 'AI Research',
            topic_color: '#FF9A00',
            source_url: 'https://techcrunch.com/ai-news',
            created_at: new Date(Date.now() - 3600000).toISOString()
        },
        {
            spark_id: 's2',
            title: 'Battery Revolution',
            content_preview: 'New battery technology promises 1000km range for electric vehicles',
            content: 'New battery technology promises 1000km range for electric vehicles. Solid-state batteries could hit market by 2027.',
            topic_title: 'Climate Tech',
            topic_color: '#22C55E',
            source_url: 'https://arstechnica.com/science',
            created_at: new Date(Date.now() - 86400000).toISOString()
        }
    ];

    // Demo alerts
    State.alerts = [
        {
            page_title: 'OpenAI announces new model',
            page_url: 'https://openai.com/blog',
            idea_box_name: 'AI Research',
            strength: 3,
            source: 'auto'
        },
        {
            page_title: 'Solar efficiency breakthrough',
            page_url: 'https://nature.com/articles',
            idea_box_name: 'Climate Tech',
            strength: 2
        }
    ];

    // Demo page info
    State.pageInfo = {
        title: 'Preview Mode - Spark Catcher',
        url: 'https://example.com/preview',
        favicon: ''
    };

    // Demo monitored pages
    State.monitoredPages = [
        { id: 'p1', url: 'https://techcrunch.com', status: 'ok', last_checked: new Date().toISOString() },
        { id: 'p2', url: 'https://arstechnica.com', status: 'ok', last_checked: new Date().toISOString() }
    ];

    // Update UI
    updateUserUI();
    renderIdeaBoxSelect();
    renderSparksList();
    renderAlertsList();
    renderPagesList();
    updateAlertsBadge();

    $('page-title').textContent = State.pageInfo.title;
    $('page-url').textContent = State.pageInfo.url;
    $('source-url').value = State.pageInfo.url;
    $('sparks-count').textContent = `${State.sparks.length} sparks`;

    // Show main view
    showView('main-view');

    // Add preview banner
    const banner = document.createElement('div');
    banner.style.cssText = 'background:#FEF3C7;color:#92400E;padding:6px 12px;font-size:11px;text-align:center;border-bottom:1px solid #FCD34D;';
    banner.textContent = '⚡ Preview Mode - Install extension for full functionality';
    document.body.insertBefore(banner, document.body.firstChild);
}

// ============================================
// LOCAL AI STATUS
// ============================================

/**
 * Check the status of the local AI model and update the UI.
 * Called when opening settings modal.
 */
async function checkAIStatus() {
    const badge = $('ai-status-badge');
    const hint = $('ai-status-hint');

    if (!badge || !hint) return;

    // Preview mode - show disabled
    if (State.isPreviewMode) {
        badge.textContent = 'Preview';
        badge.className = 'encryption-badge inactive';
        hint.textContent = 'Install extension to enable';
        return;
    }

    // Initial state
    badge.textContent = '...';
    badge.className = 'encryption-badge inactive';
    hint.textContent = 'Checking model status...';

    try {
        // Ask background script for AI status
        const response = await chrome.runtime.sendMessage({ action: 'GET_LOCAL_AI_STATUS' });

        if (response && response.success) {
            const status = response.status;

            if (status.modelLoaded) {
                badge.textContent = 'Ready';
                badge.className = 'encryption-badge active';
                hint.textContent = `${status.modelName || 'multilingual-e5-small'} loaded`;
            } else if (status.modelInitializing) {
                badge.textContent = 'Loading';
                badge.className = 'encryption-badge locked';
                hint.textContent = 'Model is loading...';
            } else {
                badge.textContent = 'Idle';
                badge.className = 'encryption-badge inactive';
                hint.textContent = 'Model loads on first use';
            }
        } else {
            badge.textContent = 'N/A';
            badge.className = 'encryption-badge inactive';
            hint.textContent = 'Could not check status';
        }
    } catch (error) {
        console.log('[POPUP] AI status check failed:', error);
        badge.textContent = 'Error';
        badge.className = 'encryption-badge inactive';
        hint.textContent = 'Status unavailable';
    }
}
