// Sidepanel script for Overleaf Document Reader Extension
// 主入口文件 - 全局变量、初始化、消息监听

// =================== UI 缩放设置 ===================
// 手动调节插件界面缩放
let currentZoomLevel = 100; // 百分比，默认 100%
const MIN_ZOOM = 50;  // 最小 50%
const MAX_ZOOM = 150; // 最大 150%
const ZOOM_STEP = 10; // 每次调整 10%

/**
 * 应用缩放级别到 UI
 */
function applyZoomLevel(zoomPercent) {
    currentZoomLevel = zoomPercent;
    const scale = zoomPercent / 100;
    document.documentElement.style.setProperty('--ui-scale', scale);

    // 更新显示
    const display = document.getElementById('ui-zoom-display');
    if (display) {
        display.textContent = `${zoomPercent}%`;
    }

    console.log('[Sidepanel] Applied zoom level:', zoomPercent + '%');
}

/**
 * 保存缩放级别设置
 */
async function saveZoomLevel(zoomPercent) {
    try {
        await chrome.storage.sync.set({ uiZoomLevel: zoomPercent });
        console.log('[Sidepanel] Zoom level saved:', zoomPercent + '%');
    } catch (error) {
        console.error('[Sidepanel] Error saving zoom level:', error);
    }
}

/**
 * 初始化缩放控制
 */
async function initZoomControl() {
    // 从存储加载缩放设置
    try {
        const result = await chrome.storage.sync.get(['uiZoomLevel']);
        if (result.uiZoomLevel) {
            applyZoomLevel(result.uiZoomLevel);
        }
    } catch (error) {
        console.log('[Sidepanel] Could not load zoom level:', error.message);
    }

    // 缩小按钮
    const decreaseBtn = document.getElementById('ui-zoom-decrease');
    if (decreaseBtn) {
        decreaseBtn.addEventListener('click', () => {
            const newZoom = Math.max(MIN_ZOOM, currentZoomLevel - ZOOM_STEP);
            applyZoomLevel(newZoom);
            saveZoomLevel(newZoom);
        });
    }

    // 放大按钮
    const increaseBtn = document.getElementById('ui-zoom-increase');
    if (increaseBtn) {
        increaseBtn.addEventListener('click', () => {
            const newZoom = Math.min(MAX_ZOOM, currentZoomLevel + ZOOM_STEP);
            applyZoomLevel(newZoom);
            saveZoomLevel(newZoom);
        });
    }
}

// =================== 全局变量 ===================
let currentContent = '';
let currentFileName = '';
let modifiedContent = '';
let selectedText = '';
let selectedTextSource = '';
let isTranslationModalOpen = false;
let workOriginalText = '';
let workOriginalChinese = '';
let selectedModel = 'doubao-translation'; // Default model (高级模型)
let currentPageId = 'home-page'; // 跟踪当前页面
let filePollingInterval = null; // 文件名轮询定时器

// Compact mode - 简略模式（嵌入到 Overleaf 页面）
let isCompactMode = false;

// Authentication
let currentUser = null;

// =================== 认证服务初始化 ===================
async function initAuthService() {
    console.log('[Sidepanel] Initializing auth service...');

    // 初始化认证服务
    if (typeof authService !== 'undefined') {
        try {
            await authService.init();
            // 从 overleaf.top 同步登录状态
            const user = await authService.syncLoginStatus();
            if (user) {
                currentUser = user;
                console.log('[Sidepanel] User logged in:', user.nickname);
            } else {
                console.log('[Sidepanel] User not logged in');
            }
        } catch (error) {
            console.error('[Sidepanel] Auth init error:', error);
        }
    } else {
        console.warn('[Sidepanel] authService not available');
    }

    await updateAuthUI();
}

async function updateAuthUI() {
    const authSection = document.getElementById('auth-section');
    const loginPrompt = document.getElementById('login-prompt');
    const userProfile = document.getElementById('user-profile');

    if (!authSection) return;

    // 显示认证区域
    authSection.style.display = 'block';

    if (currentUser) {
        // User is logged in
        if (loginPrompt) loginPrompt.style.display = 'none';
        if (userProfile) {
            userProfile.style.display = 'block';
            document.getElementById('user-avatar').src = currentUser.avatar_url || '';
            document.getElementById('user-nickname').textContent = currentUser.nickname || 'User';
            document.getElementById('user-tokens').textContent = Math.floor(currentUser.remaining_tokens || 0);

            // Update VIP status
            const vipStatus = await authService.checkVipStatus();
            updateVipDisplay(vipStatus);
        }
    } else {
        // User is not logged in
        if (loginPrompt) loginPrompt.style.display = 'block';
        if (userProfile) userProfile.style.display = 'none';
    }
}

// =================== 模型选择 ===================
// 翻译模型（边写边译使用）- 使用 HTML 中的 selected 属性作为默认值
function getSelectedModel() {
    const modelSelectEl = document.getElementById('live-translation-model-select');
    return modelSelectEl ? modelSelectEl.value : 'doubao-lite';
}

// 不再从存储加载，使用 HTML 默认值
function loadModelSelection() {
    // 使用 HTML 中的 selected 属性作为默认值
}

// 不再保存模型选择到存储
function saveModelSelection() {
    // 不再保存模型选择
}

// =================== 氛围写作模型选择 ===================
// 氛围写作模型 - 使用 HTML 中的 selected 属性作为默认值
async function getSelectedAmbientModel() {
    const modelSelectEl = document.getElementById('ambient-writing-model-select');
    return modelSelectEl ? modelSelectEl.value : 'doubao-translation';
}

// 不再从存储加载，使用 HTML 默认值
async function loadAmbientModelSelection() {
    // 使用 HTML 中的 selected 属性作为默认值
}

// 不再保存模型选择到存储
async function saveAmbientModelSelection() {
    // 不再保存模型选择
}

// =================== 思考程度选择 ===================
// 模型类型判断函数
function isDoubaoFlashModel(model) {
    return model === 'doubao-flash';
}

function isDoubaoSeedModel(model) {
    return model === 'doubao-translation' || model === 'doubao-lite';
}

function isGeminiFlashModel(model) {
    return model === 'gemini-2.5-flash' || model === 'gemini-2.5-flash-lite';
}

function isGeminiProModel(model) {
    return model === 'gemini-3-pro';
}

function isGeminiModel(model) {
    return model && model.startsWith('gemini-');
}

// 判断模型是否支持思考程度设置（免费模型不支持）
function supportsThinkingSetting(model) {
    return model !== 'microsoft-translator';
}

// 获取翻译模型对应的选择器元素ID
function getThinkingSelectId(model) {
    if (isDoubaoFlashModel(model)) return 'thinking-type-select';
    if (isDoubaoSeedModel(model)) return 'reasoning-effort-select';
    if (isGeminiFlashModel(model)) return 'gemini-flash-thinking-select';
    if (isGeminiProModel(model)) return 'gemini-pro-thinking-select';
    return null;
}

// 获取氛围写作模型对应的选择器元素ID
function getAmbientThinkingSelectId(model) {
    if (isDoubaoFlashModel(model)) return 'ambient-thinking-type-select';
    if (isDoubaoSeedModel(model)) return 'ambient-reasoning-effort-select';
    if (isGeminiFlashModel(model)) return 'ambient-gemini-flash-thinking-select';
    if (isGeminiProModel(model)) return 'ambient-gemini-pro-thinking-select';
    return null;
}

// 获取翻译模型对应的存储键
function getThinkingStorageKey(model) {
    if (isDoubaoFlashModel(model)) return 'thinkingType_doubao-flash';
    if (isDoubaoSeedModel(model)) return `reasoningEffort_${model}`;
    if (isGeminiModel(model)) return `thinkingEffort_${model}`;
    return null;
}

// 获取氛围写作模型对应的存储键
function getAmbientThinkingStorageKey(model) {
    if (isDoubaoFlashModel(model)) return 'ambient_thinkingType_doubao-flash';
    if (isDoubaoSeedModel(model)) return `ambient_reasoningEffort_${model}`;
    if (isGeminiModel(model)) return `ambient_thinkingEffort_${model}`;
    return null;
}

// 获取翻译模型的默认思考参数值（初等模型默认第二档，保证格式输出正确）
function getDefaultThinkingValue(model) {
    if (isDoubaoFlashModel(model)) return 'disabled';  // doubao-flash 默认: 关闭
    if (isDoubaoSeedModel(model)) return 'low';        // doubao-seed 默认: 简单（第二档）
    if (isGeminiFlashModel(model)) return 'low';       // gemini-flash 默认: 简单（第二档）
    if (isGeminiProModel(model)) return 'low';         // gemini-3-pro 默认: 简单 (它只有 low/high 两档)
    return 'low';
}

// 获取氛围写作模型的默认思考参数值（氛围写作默认简单，保证质量）
function getDefaultAmbientThinkingValue(model) {
    if (isDoubaoFlashModel(model)) return 'auto';      // doubao-flash 默认: 自动
    if (isDoubaoSeedModel(model)) return 'low';        // doubao-seed 默认: 简单
    if (isGeminiFlashModel(model)) return 'low';       // gemini-flash 默认: 简单
    if (isGeminiProModel(model)) return 'low';         // gemini-3-pro 默认: 简单
    return 'low';
}

// 根据翻译模型切换显示对应的思考程度选择器
function updateThinkingSelectVisibility(model) {
    const reasoningEffortSelect = document.getElementById('reasoning-effort-select');
    const thinkingTypeSelect = document.getElementById('thinking-type-select');
    const geminiFlashSelect = document.getElementById('gemini-flash-thinking-select');
    const geminiProSelect = document.getElementById('gemini-pro-thinking-select');

    // 隐藏所有选择器
    if (reasoningEffortSelect) reasoningEffortSelect.classList.add('hidden');
    if (thinkingTypeSelect) thinkingTypeSelect.classList.add('hidden');
    if (geminiFlashSelect) geminiFlashSelect.classList.add('hidden');
    if (geminiProSelect) geminiProSelect.classList.add('hidden');

    if (!supportsThinkingSetting(model)) {
        return; // 免费模型：所有选择器都隐藏
    }

    // 显示对应模型的选择器
    const selectId = getThinkingSelectId(model);
    if (selectId) {
        const select = document.getElementById(selectId);
        if (select) select.classList.remove('hidden');
    }
}

// 根据氛围写作模型切换显示对应的思考程度选择器
function updateAmbientThinkingSelectVisibility(model) {
    const reasoningEffortSelect = document.getElementById('ambient-reasoning-effort-select');
    const thinkingTypeSelect = document.getElementById('ambient-thinking-type-select');
    const geminiFlashSelect = document.getElementById('ambient-gemini-flash-thinking-select');
    const geminiProSelect = document.getElementById('ambient-gemini-pro-thinking-select');

    // 隐藏所有选择器
    if (reasoningEffortSelect) reasoningEffortSelect.classList.add('hidden');
    if (thinkingTypeSelect) thinkingTypeSelect.classList.add('hidden');
    if (geminiFlashSelect) geminiFlashSelect.classList.add('hidden');
    if (geminiProSelect) geminiProSelect.classList.add('hidden');

    // 显示对应模型的选择器（氛围写作没有免费模型）
    const selectId = getAmbientThinkingSelectId(model);
    if (selectId) {
        const select = document.getElementById(selectId);
        if (select) select.classList.remove('hidden');
    }
}

// 获取当前选中的思考参数值（翻译模型）
// 不再从存储读取，直接使用当前 DOM 值或默认值
function getSelectedReasoningEffort() {
    const model = getSelectedModel();

    if (!supportsThinkingSetting(model)) {
        return null; // 免费模型不需要思考参数
    }

    const selectId = getThinkingSelectId(model);
    if (selectId) {
        const select = document.getElementById(selectId);
        if (select) {
            return select.value;
        }
    }

    return getDefaultThinkingValue(model);
}

// 获取氛围写作模型的思考参数值
async function getSelectedAmbientReasoningEffort() {
    const model = await getSelectedAmbientModel();

    const selectId = getAmbientThinkingSelectId(model);
    if (selectId) {
        const select = document.getElementById(selectId);
        if (select) {
            return select.value;
        }
    }

    // Fallback to stored value
    const storageKey = getAmbientThinkingStorageKey(model);
    if (storageKey) {
        const result = await chrome.storage.sync.get([storageKey]);
        return result[storageKey] || getDefaultAmbientThinkingValue(model);
    }

    return getDefaultAmbientThinkingValue(model);
}

// 加载翻译模型思考程度选择
// 不再从存储加载，只更新选择器可见性，使用 HTML 默认值
function loadReasoningEffortSelection() {
    const model = getSelectedModel();
    // 只更新选择器可见性
    updateThinkingSelectVisibility(model);
}

// 加载氛围写作模型思考程度选择
async function loadAmbientReasoningEffortSelection() {
    try {
        const model = await getSelectedAmbientModel();

        // 更新选择器可见性
        updateAmbientThinkingSelectVisibility(model);

        const selectId = getAmbientThinkingSelectId(model);
        const storageKey = getAmbientThinkingStorageKey(model);

        if (selectId && storageKey) {
            const result = await chrome.storage.sync.get([storageKey]);
            const select = document.getElementById(selectId);
            if (select && result[storageKey]) {
                select.value = result[storageKey];
            }
        }
    } catch (error) {
        console.error('[Sidepanel] Error loading ambient reasoning effort selection:', error);
    }
}

// 保存翻译模型思考程度选择
// 不再保存到存储
function saveReasoningEffortSelection() {
    // 不再保存思考程度设置
}

// 保存氛围写作模型思考程度选择
async function saveAmbientReasoningEffortSelection() {
    try {
        const model = await getSelectedAmbientModel();

        const selectId = getAmbientThinkingSelectId(model);
        const storageKey = getAmbientThinkingStorageKey(model);

        if (selectId && storageKey) {
            const select = document.getElementById(selectId);
            if (select) {
                await chrome.storage.sync.set({ [storageKey]: select.value });
                console.log(`[Sidepanel] Ambient thinking setting saved for ${model}:`, select.value);
            }
        }
    } catch (error) {
        console.error('[Sidepanel] Error saving ambient reasoning effort selection:', error);
    }
}

// 翻译模型改变时的处理函数
async function onModelChange() {
    const modelSelectEl = document.getElementById('live-translation-model-select');
    const selectedModel = modelSelectEl ? modelSelectEl.value : '';

    // 检查是否选择了 Gemini 模型，如果是普通会员则不允许
    if (selectedModel.startsWith('gemini-')) {
        try {
            const vipStatus = await authService.checkVipStatus();
            if (vipStatus.vipLevel === 1) {
                // 普通会员不允许使用 Gemini 模型，重置为默认模型
                if (modelSelectEl) {
                    modelSelectEl.value = 'doubao-lite';
                }
                showError('普通会员不支持使用 Gemini 模型，请升级至 Pro 或 Pro Max 会员');
                loadReasoningEffortSelection();
                return;
            }
        } catch (error) {
            console.error('[Sidepanel] Failed to check VIP status:', error);
            // 验证失败时，重置为默认模型
            if (modelSelectEl) {
                modelSelectEl.value = 'doubao-lite';
            }
            showError('无法验证会员状态，请确保已登录');
            loadReasoningEffortSelection();
            return;
        }
    }

    loadReasoningEffortSelection(); // 这会更新选择器可见性
}

// 氛围写作模型改变时的处理函数
async function onAmbientModelChange() {
    await saveAmbientModelSelection();
    await loadAmbientReasoningEffortSelection(); // 这会更新选择器可见性并加载对应的设置
}

// =================== 文档内容管理 ===================
async function updateStatus(isConnected) {
    const docStatusEl = document.getElementById('doc-status');

    // 使用新的UI函数更新连接状态
    updateConnectionStatus(isConnected);

    if (docStatusEl) {
        docStatusEl.textContent = isConnected ? '就绪' : '等待连接';
    }
}

async function requestContent() {
    try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

        if (!tab || !tab.url || !tab.url.includes('overleaf.com')) {
            await updateStatus(false);
            return;
        }

        await updateStatus(true);

        // 使用 Promise 包装，确保等待回调完成
        await new Promise((resolve) => {
            chrome.tabs.sendMessage(tab.id, { type: 'GET_DOCUMENT_CONTENT' }, async (response) => {
                if (chrome.runtime.lastError) {
                    console.error('[Sidepanel] Error:', chrome.runtime.lastError);
                    await getStoredContent();
                    resolve();
                    return;
                }

                if (response && response.content) {
                    // 先更新文件名，再更新内容，确保 initLiveTranslation 使用正确的文件名
                    // 注意：content.js 返回的是 filename (小写)
                    currentFileName = response.filename || response.fileName || 'document.tex';
                    await updateContent(response.content, response.length);
                    if (response.timestamp) {
                        updateLastUpdateTime(response.timestamp);
                    }
                } else {
                    await getStoredContent();
                }
                resolve();
            });
        });
    } catch (error) {
        console.error('[Sidepanel] Error requesting content:', error);
        await updateStatus(false);
    }
}

async function getStoredContent() {
    return new Promise((resolve) => {
        chrome.storage.local.get(['overleafContent', 'overleafFileName'], async (result) => {
            if (result.overleafContent) {
                currentContent = result.overleafContent;
                currentFileName = result.overleafFileName || 'document.tex';
                document.getElementById('doc-status').textContent = '从存储加载';

                // 启用按钮并初始化翻译功能
                document.getElementById('upload-project-btn').disabled = false;

                // 只在首次时初始化
                if (!liveTranslationInitialized) {
                    await initLiveTranslation();
                    liveTranslationInitialized = true;
                }
            } else {
                document.getElementById('doc-status').textContent = '无可用内容';
            }
            resolve();
        });
    });
}

// 标记是否已经初始化过边写边译功能
let liveTranslationInitialized = false;

async function updateContent(content, length) {
    currentContent = content;

    // 保存到存储
    chrome.storage.local.set({
        overleafContent: content,
        overleafFileName: currentFileName
    });

    document.getElementById('doc-status').textContent = '文档已加载';
    document.getElementById('content-length').textContent = length.toLocaleString();

    // Enable buttons when content is available
    if (content && content.length > 0) {
        // Enable buttons
        document.getElementById('upload-project-btn').disabled = false;

        // 只在首次时初始化边写边译功能，避免后续内容更新时重新加载覆盖编辑器内容
        if (!liveTranslationInitialized) {
            await initLiveTranslation();
            liveTranslationInitialized = true;
        }
    }
}

// =================== 下载和上传编译功能 ===================
async function uploadProjectZipToServer(showMessages = true) {
    try {
        // Get project ID from URL
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        if (!tab || !tab.url) {
            if (showMessages) showError('Cannot get current tab');
            return false;
        }

        const urlMatch = tab.url.match(/\/project\/([a-f0-9]+)/);
        if (!urlMatch) {
            if (showMessages) showError('Cannot extract project ID from URL');
            return false;
        }
        const projectId = urlMatch[1];

        if (showMessages) showSuccess('正在获取项目 ZIP...', true);

        // Request ZIP file from content script
        const response = await new Promise((resolve, reject) => {
            chrome.tabs.sendMessage(tab.id, { type: 'GET_PROJECT_ZIP' }, (response) => {
                if (chrome.runtime.lastError) {
                    reject(new Error(chrome.runtime.lastError.message));
                } else {
                    resolve(response);
                }
            });
        });

        if (!response || !response.success || !response.zipData) {
            if (showMessages) showError('获取项目 ZIP 失败');
            return false;
        }

        if (showMessages) showSuccess('正在上传并编译...', true);

        // Convert base64 to blob
        const binaryString = atob(response.zipData);
        const bytes = new Uint8Array(binaryString.length);
        for (let i = 0; i < binaryString.length; i++) {
            bytes[i] = binaryString.charCodeAt(i);
        }
        const zipBlob = new Blob([bytes], { type: 'application/zip' });

        // Create form data
        const formData = new FormData();
        formData.append('file', zipBlob, `${projectId}.zip`);

        // Add current tex filename if available (for specifying which file to compile)
        if (currentFileName && currentFileName.endsWith('.tex')) {
            formData.append('main_file', currentFileName);
        }

        // Create AbortController for timeout (10 minutes)
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 10 * 60 * 1000);

        // Upload to server and compile
        const uploadResponse = await fetch(`${BACKEND_API_URL}/api/projects/${projectId}/compile`, {
            method: 'POST',
            credentials: 'include',
            body: formData,
            signal: controller.signal
        });

        clearTimeout(timeoutId);

        // Check if response is PDF (success) or JSON (error)
        const contentType = uploadResponse.headers.get('content-type');

        if (uploadResponse.ok && contentType && contentType.includes('application/pdf')) {
            // Success - PDF returned
            const pdfBlob = await uploadResponse.blob();
            const pdfUrl = URL.createObjectURL(pdfBlob);

            // Get token info from headers
            const consumedTokens = uploadResponse.headers.get('X-Consumed-Tokens');
            const remainingTokens = uploadResponse.headers.get('X-Remaining-Tokens');

            // Show PDF preview modal
            showPdfPreview(pdfUrl, `${projectId}.pdf`);

            if (showMessages) {
                let message = '编译成功！';
                if (consumedTokens) {
                    message += `（消耗 ${consumedTokens} 点数）`;
                }
                showSuccess(message);
            }

            // Update user tokens display if available
            if (remainingTokens && typeof updateUserTokensDisplay === 'function') {
                updateUserTokensDisplay(parseInt(remainingTokens));
            }

            return true;

        } else {
            // Error - JSON response
            const errorData = await uploadResponse.json().catch(() => ({}));

            if (uploadResponse.status === 422) {
                // Compilation failed - show full log in modal
                console.error('[Sidepanel] Compilation failed:', errorData);
                const errorMsg = errorData.error || '编译失败';
                const log = errorData.log || '';
                console.log('[Sidepanel] Compilation log:', log);

                if (showMessages) {
                    // Show log modal with full compile log
                    showCompileLog(errorMsg, log);
                }
            } else if (uploadResponse.status === 402) {
                // Insufficient tokens
                if (showMessages) showError(errorData.detail || '点数不足');
            } else {
                // Other errors
                throw new Error(errorData.detail || `上传失败: ${uploadResponse.status}`);
            }

            return false;
        }

    } catch (error) {
        console.error('[Sidepanel] Upload/compile error:', error);
        if (error.name === 'AbortError') {
            if (showMessages) showError('编译超时（超过10分钟）');
        } else {
            if (showMessages) showError('上传/编译失败: ' + error.message);
        }
        return false;
    }
}

// =================== PDF 预览功能 ===================
let currentPdfUrl = null;
let currentPdfFilename = null;

function showPdfPreview(pdfUrl, filename) {
    currentPdfUrl = pdfUrl;
    currentPdfFilename = filename;

    const modal = document.getElementById('pdf-preview-modal');
    const iframe = document.getElementById('pdf-preview-iframe');
    const filenameSpan = document.getElementById('pdf-preview-filename');

    if (modal && iframe) {
        filenameSpan.textContent = filename;
        iframe.src = pdfUrl;
        modal.classList.remove('hidden');
    }
}

function closePdfPreview() {
    const modal = document.getElementById('pdf-preview-modal');
    const iframe = document.getElementById('pdf-preview-iframe');

    if (modal) {
        modal.classList.add('hidden');
    }
    if (iframe) {
        iframe.src = '';
    }

    // Revoke the blob URL to free memory
    if (currentPdfUrl) {
        URL.revokeObjectURL(currentPdfUrl);
        currentPdfUrl = null;
    }
    currentPdfFilename = null;
}

function savePdfToLocal() {
    if (currentPdfUrl && currentPdfFilename) {
        chrome.downloads.download({
            url: currentPdfUrl,
            filename: currentPdfFilename,
            saveAs: true
        }, () => {
            showSuccess('PDF 已保存！');
        });
    }
}

// Setup PDF preview event handlers
document.getElementById('pdf-close-btn')?.addEventListener('click', closePdfPreview);
document.getElementById('pdf-modal-backdrop')?.addEventListener('click', closePdfPreview);
document.getElementById('pdf-save-btn')?.addEventListener('click', savePdfToLocal);

// =================== 编译日志功能 ===================
let currentCompileLog = '';

function showCompileLog(errorMsg, log) {
    currentCompileLog = log || '';

    const modal = document.getElementById('compile-log-modal');
    const errorSpan = document.getElementById('compile-log-error');
    const logContent = document.getElementById('compile-log-content');

    if (modal && logContent) {
        errorSpan.textContent = errorMsg || '';
        logContent.textContent = log || '无日志信息';
        modal.classList.remove('hidden');
    }
}

function closeCompileLog() {
    const modal = document.getElementById('compile-log-modal');
    if (modal) {
        modal.classList.add('hidden');
    }
    currentCompileLog = '';
}

function copyCompileLog() {
    if (currentCompileLog) {
        navigator.clipboard.writeText(currentCompileLog).then(() => {
            showSuccess('日志已复制到剪贴板！');
        }).catch(() => {
            showError('复制失败');
        });
    }
}

// Setup compile log event handlers
document.getElementById('log-close-btn')?.addEventListener('click', closeCompileLog);
document.getElementById('log-modal-backdrop')?.addEventListener('click', closeCompileLog);
document.getElementById('log-copy-btn')?.addEventListener('click', copyCompileLog);

// =================== 认证事件处理器设置 ===================
function setupAuthEventHandlers() {
    // Wechat login button
    const wechatLoginBtn = document.getElementById('wechat-login-btn');
    if (wechatLoginBtn) {
        wechatLoginBtn.addEventListener('click', async () => {
            // 打开登录页面
            chrome.tabs.create({
                url: 'https://overleaf.top/wechat/auth',
                active: true
            });
        });

        // 添加同步登录状态按钮
        const loginPrompt = document.getElementById('login-prompt');
        if (loginPrompt && !document.getElementById('sync-auth-btn')) {
            const syncBtn = document.createElement('button');
            syncBtn.id = 'sync-auth-btn';
            syncBtn.className = 'mt-3 px-4 py-2 bg-slate-100 hover:bg-slate-200 text-slate-600 rounded-lg text-sm font-medium transition-colors';
            syncBtn.textContent = '同步登录状态';
            syncBtn.addEventListener('click', async () => {
                syncBtn.disabled = true;
                syncBtn.textContent = '同步中...';
                try {
                    await initAuthService();
                    await updateAuthUI();
                    if (currentUser) {
                        showSuccess('登录状态已同步！');
                    } else {
                        showError('未检测到登录状态，请先在 overleaf.top 登录');
                    }
                } finally {
                    syncBtn.disabled = false;
                    syncBtn.textContent = '同步登录状态';
                }
            });
            loginPrompt.appendChild(syncBtn);
        }
    }

    // 顶部同步登录状态按钮
    const syncLoginBtn = document.getElementById('sync-login-btn');
    if (syncLoginBtn) {
        syncLoginBtn.addEventListener('click', async () => {
            const icon = syncLoginBtn.querySelector('svg');
            if (icon) icon.classList.add('animate-spin');
            try {
                await initAuthService();
                await updateAuthUI();
                if (currentUser) {
                    showSuccess('登录状态已同步！');
                } else {
                    showError('未检测到登录状态');
                }
            } finally {
                if (icon) icon.classList.remove('animate-spin');
            }
        });
    }

    // Profile button
    const profileBtn = document.getElementById('profile-btn');
    if (profileBtn) {
        profileBtn.addEventListener('click', () => {
            showProfilePage();
        });
    }

    // Profile back button
    const profileBackBtn = document.getElementById('profile-back-btn');
    if (profileBackBtn) {
        profileBackBtn.addEventListener('click', () => {
            goToHomePage();
        });
    }

    // Logout button
    const logoutBtn = document.getElementById('logout-btn');
    if (logoutBtn) {
        logoutBtn.addEventListener('click', async () => {
            try {
                await authService.logout();
                currentUser = null;
                await updateAuthUI();
                goToHomePage();
                showSuccess('已退出登录');
            } catch (error) {
                console.error('[Sidepanel] Logout error:', error);
                showError('退出登录失败');
            }
        });
    }

    // Close payment modal button
    const closePaymentModalBtn = document.getElementById('close-payment-modal');
    if (closePaymentModalBtn) {
        closePaymentModalBtn.addEventListener('click', () => {
            closePaymentModal();
        });
    }
}

// =================== 简略模式检测 ===================
// 简略模式的视图类型: 'translation' 或 'ambient-writing'
let compactViewType = 'translation';

function checkCompactMode() {
    const urlParams = new URLSearchParams(window.location.search);
    isCompactMode = urlParams.get('mode') === 'compact';
    compactViewType = urlParams.get('view') || 'translation';
    console.log('[Sidepanel] Compact mode:', isCompactMode, ', view type:', compactViewType);
    return isCompactMode;
}

/**
 * 初始化简略模式 - 根据 view 参数显示边写边译或氛围写作
 */
function initCompactModeUI() {
    if (!isCompactMode) return;

    // 添加 compact-mode class 到 body，用 CSS 控制样式
    document.body.classList.add('compact-mode');

    // 隐藏除了边写边译/氛围写作之外的所有内容
    const elementsToHide = [
        'auth-section',           // 认证区域
        'profile-page',           // 个人页面
        'autocite-page',          // 自动引用页面
        'live-translation-page',  // 翻译页面（旧的）
        'payment-modal'           // 支付弹窗
    ];

    elementsToHide.forEach(id => {
        const el = document.getElementById(id);
        if (el) {
            el.style.display = 'none';
        }
    });

    // 隐藏首页中除了目标容器之外的部分
    const homePage = document.getElementById('home-page');
    const zhPreviewContainer = homePage?.querySelector('.zh-preview-container');
    const llmChatWrapper = document.getElementById('llm-chat-wrapper');

    if (homePage) {
        // 找到并隐藏不需要的元素（通过遍历子元素）
        const children = homePage.children;
        for (let i = 0; i < children.length; i++) {
            const child = children[i];
            // 根据模式决定保留哪个容器
            if (compactViewType === 'ambient-writing') {
                // 氛围写作模式：只保留 llm-chat-wrapper
                if (child.id !== 'llm-chat-wrapper') {
                    child.style.display = 'none';
                }
            } else {
                // 边写边译模式：只保留 zh-preview-container
                if (!child.classList.contains('zh-preview-container')) {
                    child.style.display = 'none';
                }
            }
        }

        // 根据模式设置容器样式
        if (compactViewType === 'ambient-writing') {
            // 氛围写作模式
            if (zhPreviewContainer) {
                zhPreviewContainer.style.display = 'none';
            }
            if (llmChatWrapper) {
                llmChatWrapper.style.display = 'flex';
                llmChatWrapper.classList.add('active');
                llmChatWrapper.style.flex = '1';
                llmChatWrapper.style.margin = '0';
                llmChatWrapper.style.borderRadius = '0';
                llmChatWrapper.style.boxShadow = 'none';
            }
        } else {
            // 边写边译模式
            if (zhPreviewContainer) {
                zhPreviewContainer.style.display = 'flex';
                zhPreviewContainer.style.flex = '1';
                zhPreviewContainer.style.margin = '0';
                zhPreviewContainer.style.borderRadius = '0';
                zhPreviewContainer.style.border = 'none';
                zhPreviewContainer.style.boxShadow = 'none';
            }
            if (llmChatWrapper) {
                llmChatWrapper.style.display = 'none';
            }
        }
    }

    // 隐藏顶部工具栏的简略视图按钮（在简略模式下不需要）
    const compactViewBtn = document.getElementById('compact-view-btn');
    if (compactViewBtn) {
        compactViewBtn.style.display = 'none';
    }

    // 返回完整视图的通用处理函数
    function returnToFullView() {
        window.parent.postMessage({ type: 'COMPACT_VIEW_RETURN_TO_SIDEPANEL' }, '*');
    }

    // 显示并设置边写边译的"返回完整视图"按钮
    const returnFullViewBtn = document.getElementById('return-full-view-btn');
    if (returnFullViewBtn) {
        returnFullViewBtn.classList.remove('hidden');
        returnFullViewBtn.addEventListener('click', returnToFullView);
    }

    // 显示并设置氛围写作的"返回完整视图"按钮
    const llmReturnFullViewBtn = document.getElementById('llm-return-full-view-btn');
    if (llmReturnFullViewBtn) {
        llmReturnFullViewBtn.classList.remove('hidden');
        llmReturnFullViewBtn.addEventListener('click', returnToFullView);
    }

    // 显示并设置边写边译的"氛围写作"切换按钮（简略模式专用）
    const switchToAmbientBtn = document.getElementById('switch-to-ambient-btn');
    if (switchToAmbientBtn) {
        switchToAmbientBtn.classList.remove('hidden');
        switchToAmbientBtn.addEventListener('click', () => {
            if (typeof enterAmbientWritingMode === 'function') {
                enterAmbientWritingMode();
            }
        });
    }

    console.log('[Sidepanel] Compact mode UI initialized, view type:', compactViewType);
}

// =================== 侧边栏状态通知 ===================
// 通知 content script 侧边栏打开/关闭状态
async function notifySidepanelState(isOpen) {
    try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        if (tab && tab.id) {
            chrome.runtime.sendMessage({
                type: isOpen ? 'SIDEPANEL_OPENED' : 'SIDEPANEL_CLOSED',
                tabId: tab.id
            }).catch(() => {});
        }
    } catch (error) {
        console.log('[Sidepanel] Could not notify sidepanel state:', error.message);
    }
}

// =================== DOM 加载完成后初始化 ===================
document.addEventListener('DOMContentLoaded', async () => {
    console.log('[Sidepanel] DOM loaded, initializing...');

    // 通知 content script 侧边栏已打开
    notifySidepanelState(true);

    // 监听侧边栏关闭（页面卸载）
    window.addEventListener('beforeunload', () => {
        notifySidepanelState(false);
    });

    // 初始化 UI 缩放控制
    await initZoomControl();

    // 检测简略模式
    checkCompactMode();

    // 初始化认证服务
    await initAuthService();

    // 设置认证事件处理器
    setupAuthEventHandlers();

    // 设置VIP购买按钮
    setupVipButtons();

    // 设置模型切换事件监听（使用 HTML 中的 selected 属性作为默认值）
    const modelSelectEl = document.getElementById('live-translation-model-select');
    if (modelSelectEl) {
        modelSelectEl.addEventListener('change', onModelChange);
    }

    // 初始化翻译模型思考程度选择器可见性
    loadReasoningEffortSelection();
    // 为所有翻译模型思考程度选择器添加事件监听
    const thinkingSelectIds = [
        'reasoning-effort-select',      // 豆包 Seed 模型
        'thinking-type-select',         // 豆包 Flash 模型
        'gemini-flash-thinking-select', // Gemini Flash/Flash-Lite 模型
        'gemini-pro-thinking-select'    // Gemini Pro 模型
    ];
    thinkingSelectIds.forEach(id => {
        const selectEl = document.getElementById(id);
        if (selectEl) {
            selectEl.addEventListener('change', saveReasoningEffortSelection);
        }
    });

    // 加载氛围写作模型选择
    await loadAmbientModelSelection();
    const ambientModelSelectEl = document.getElementById('ambient-writing-model-select');
    if (ambientModelSelectEl) {
        ambientModelSelectEl.addEventListener('change', onAmbientModelChange);
    }

    // 加载氛围写作模型思考程度选择
    await loadAmbientReasoningEffortSelection();
    // 为所有氛围写作模型思考程度选择器添加事件监听
    const ambientThinkingSelectIds = [
        'ambient-reasoning-effort-select',      // 豆包 Seed 模型
        'ambient-thinking-type-select',         // 豆包 Flash 模型
        'ambient-gemini-flash-thinking-select', // Gemini Flash/Flash-Lite 模型
        'ambient-gemini-pro-thinking-select'    // Gemini Pro 模型
    ];
    ambientThinkingSelectIds.forEach(id => {
        const selectEl = document.getElementById(id);
        if (selectEl) {
            selectEl.addEventListener('change', saveAmbientReasoningEffortSelection);
        }
    });

    // 初始化自动续写设置
    if (typeof initContinueWritingSettings === 'function') {
        initContinueWritingSettings();
    }

    // 初始化自动引用事件处理器
    initAutoCiteEventHandlers();

    // 初始化字号控制
    initFontSizeControl();

    // 初始化简略视图按钮
    if (typeof initCompactViewButton === 'function') {
        initCompactViewButton();
    }

    // 如果是简略模式，初始化简略模式 UI
    if (isCompactMode) {
        initCompactModeUI();
    }

    // 请求内容（带重试机制）
    await requestContent();

    // 如果首次加载没有获取到内容，多次重试
    // Overleaf 编辑器可能需要几秒钟才能完全加载
    if (!currentContent) {
        console.log('[Sidepanel] No content loaded, will retry...');

        // 重试更多次，使用更长的间隔来等待编辑器加载
        // 总共最多等待约 15 秒
        const retryDelays = [300, 500, 700, 1000, 1500, 2000, 2500, 3000, 3500];
        for (let i = 0; i < retryDelays.length; i++) {
            await new Promise(resolve => setTimeout(resolve, retryDelays[i]));
            if (!currentContent) {
                console.log(`[Sidepanel] Retry ${i + 1}/${retryDelays.length} content request...`);
                await requestContent();
            } else {
                console.log(`[Sidepanel] Content loaded successfully on retry ${i + 1}`);
                break;
            }
        }

        // 如果还是没有内容，启动持续轮询直到连接成功
        if (!currentContent) {
            console.log('[Sidepanel] Still no content, starting auto-reconnect polling...');
            startAutoReconnect();
        }
    }
});

// 自动重连轮询
let autoReconnectInterval = null;

function startAutoReconnect() {
    // 避免重复启动
    if (autoReconnectInterval) return;

    autoReconnectInterval = setInterval(async () => {
        if (currentContent) {
            // 已连接，停止轮询
            console.log('[Sidepanel] Connected, stopping auto-reconnect');
            stopAutoReconnect();
            return;
        }
        console.log('[Sidepanel] Auto-reconnect: trying to connect...');
        await requestContent();
    }, 2000);
}

function stopAutoReconnect() {
    if (autoReconnectInterval) {
        clearInterval(autoReconnectInterval);
        autoReconnectInterval = null;
    }
}

// =================== 按钮事件处理器 ===================

// Refresh button handler - refresh content and reload Chinese document
document.getElementById('refresh-btn').addEventListener('click', async () => {
    clearError();
    const btn = document.getElementById('refresh-btn');
    btn.disabled = true;
    const originalHTML = btn.innerHTML;
    btn.innerHTML = '<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> 刷新中...';

    try {
        // 1. Refresh content from Overleaf
        await requestContent();

        // 2. Re-initialize live translation (re-fetch project ID, filename, and Chinese document)
        liveTranslationInitialized = false;
        await initLiveTranslation();

        showSuccess('内容已刷新!');
    } catch (error) {
        console.error('[Sidepanel] Refresh failed:', error);
        showError('刷新内容失败');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalHTML;
    }
});

// Upload project button handler
document.getElementById('upload-project-btn').addEventListener('click', async () => {
    await uploadProjectZipToServer(true);
});

// 初始化边写边译功能（在首页直接显示）
async function initLiveTranslation() {
    console.log('[Sidepanel] Initializing live translation...');

    const fullTranslateBtn = document.getElementById('full-translate-btn');
    const reverseTranslateBtn = document.getElementById('reverse-translate-btn');
    const reloadEnglishBtn = document.getElementById('reload-english-btn');

    // 先禁用所有按钮
    fullTranslateBtn.disabled = true;
    reverseTranslateBtn.disabled = true;
    reloadEnglishBtn.disabled = true;

    if (!currentContent || !currentFileName) {
        console.log('[Sidepanel] No content loaded yet');
        return;
    }

    // 检查是否为支持边写边译的文件类型（只有 .tex 和 .txt）
    if (!isLiveTranslationFile(currentFileName)) {
        document.getElementById('zh-preview-status').textContent = '(不支持此文件类型)';
        return;
    }

    // Get project ID from URL
    try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        if (!tab || !tab.url || !tab.url.includes('overleaf.com/project/')) {
            console.log('[Sidepanel] Not on Overleaf project page');
            return;
        }

        const urlMatch = tab.url.match(/overleaf\.com\/project\/([a-f0-9]+)/);
        if (!urlMatch) {
            console.log('[Sidepanel] Cannot extract project ID');
            return;
        }
        currentProjectId = urlMatch[1];

        console.log('[Sidepanel] Current project:', currentProjectId, 'file:', currentFileName);

        // 启用翻译按钮
        fullTranslateBtn.disabled = false;
        reverseTranslateBtn.disabled = false;
        reloadEnglishBtn.disabled = false;

        // 加载已有的翻译文档（如果存在）
        await fetchZhDocument();

        // 不再自动轮询文件切换，改为用户手动点击"切换当前文档"按钮
        // startFilePolling();

    } catch (error) {
        console.error('[Sidepanel] Error initializing live translation:', error);
        // 即使出错也启用按钮
        fullTranslateBtn.disabled = false;
        reverseTranslateBtn.disabled = false;
        reloadEnglishBtn.disabled = false;
    }
}

// =================== 文件轮询检测（已废弃）===================
// 原来每秒获取一次 Overleaf 当前打开的文件名，如果变化则切换中文文档
// 现在改为用户手动点击"切换当前文档"按钮来切换

// 标志：是否正在处理文件切换（防止重入）
let isProcessingFileSwitch = false;

// 辅助函数：从 Overleaf 获取当前真实的文件名
async function getCurrentFilenameFromOverleaf(tabId) {
    return new Promise((resolve) => {
        chrome.tabs.sendMessage(tabId, { type: 'GET_CURRENT_FILENAME' }, (response) => {
            if (chrome.runtime.lastError) {
                resolve(null);
                return;
            }
            resolve(response?.filename || null);
        });
    });
}

// 辅助函数：从 Overleaf 获取当前文件的内容
async function getCurrentContentFromOverleaf(tabId) {
    return new Promise((resolve) => {
        chrome.tabs.sendMessage(tabId, { type: 'GET_FRESH_DOCUMENT_CONTENT' }, (response) => {
            if (chrome.runtime.lastError) {
                resolve(null);
                return;
            }
            resolve(response?.content || null);
        });
    });
}

function startFilePolling() {
    // 如果已经有轮询在运行，先停止
    if (filePollingInterval) {
        clearInterval(filePollingInterval);
    }

    console.log('[Sidepanel] Starting file polling...');

    filePollingInterval = setInterval(async () => {
        // 如果正在处理文件切换，跳过本次轮询
        if (isProcessingFileSwitch) {
            return;
        }

        try {
            const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
            if (!tab || !tab.url || !tab.url.includes('overleaf.com')) {
                return;
            }

            // 从URL中提取项目ID
            const urlMatch = tab.url.match(/overleaf\.com\/project\/([a-f0-9]+)/);
            const newProjectId = urlMatch ? urlMatch[1] : null;

            // 检查项目ID是否变化
            if (newProjectId && newProjectId !== currentProjectId) {
                console.log('[Sidepanel] Project changed:', currentProjectId, '->', newProjectId);
                currentProjectId = newProjectId;
            }

            // 获取 Overleaf 当前打开的文件名
            const polledFilename = await getCurrentFilenameFromOverleaf(tab.id);

            // 如果无法获取文件名，跳过
            if (!polledFilename) {
                return;
            }

            // 检查文件名是否与当前文件相同
            if (polledFilename === currentFileName) {
                // 文件没变，不需要处理
                return;
            }

            // ===== 文件切换逻辑 =====
            console.log('[Sidepanel] File switch detected:', currentFileName, '->', polledFilename);

            // 设置标志，防止重入
            isProcessingFileSwitch = true;

            // 暂停自动保存 5 秒，等待新文档加载完成
            pauseAutoSave(5);

            // 更新当前文件名
            currentFileName = polledFilename;

            // 检查文件类型并更新 UI（只有 .tex 和 .txt 支持边写边译）
            if (!isLiveTranslationFile(polledFilename)) {
                document.getElementById('zh-preview-status').textContent = '(不支持此文件类型)';
                document.getElementById('full-translate-btn').disabled = true;
                document.getElementById('reverse-translate-btn').disabled = true;
                document.getElementById('reload-english-btn').disabled = true;
                renderZhDocument('');
                isProcessingFileSwitch = false;
                return;
            }

            // 文件类型支持，启用按钮
            document.getElementById('full-translate-btn').disabled = false;
            document.getElementById('reverse-translate-btn').disabled = false;
            document.getElementById('reload-english-btn').disabled = false;

            // 加载对应的中文文档（只有当中文文档不存在时才会获取英文内容）
            console.log('[Sidepanel] Loading zh document for:', polledFilename);
            await fetchZhDocument(tab.id);

            // 加载完成后，检查是否需要再次切换（用户可能在加载期间又切换了）
            const currentPolledFilename = await getCurrentFilenameFromOverleaf(tab.id);
            if (currentPolledFilename && currentPolledFilename !== currentFileName) {
                // 用户在加载期间又切换了文件，需要重新处理
                console.log('[Sidepanel] File changed during load, will process in next poll:', currentPolledFilename);
            }

        } catch (error) {
            console.error('[Sidepanel] File polling error:', error);
        } finally {
            // 无论成功失败，都要重置标志
            isProcessingFileSwitch = false;
        }
    }, 1000); // 每秒检查一次
}

// 停止文件轮询
function stopFilePolling() {
    if (filePollingInterval) {
        clearInterval(filePollingInterval);
        filePollingInterval = null;
        console.log('[Sidepanel] File polling stopped');
    }
}

// Update character count when content changes
document.getElementById('zh-line-editor').addEventListener('input', () => {
    const content = getZhContent();
    document.getElementById('zh-content-length').textContent = content.length.toLocaleString();
});

// Full translate button handler
document.getElementById('full-translate-btn').addEventListener('click', async () => {
    if (!currentContent) {
        showError('No content to translate');
        return;
    }

    // Get model and project ID
    const model = await getSelectedModel();
    document.getElementById('zh-content-length').textContent = '0';

    // Show progress and reset to 0%
    document.getElementById('full-translate-btn').disabled = true;
    document.getElementById('translation-progress').style.display = 'block';
    document.getElementById('progress-text').textContent = '翻译进度: 0%';
    document.getElementById('progress-bar').style.width = '0%';

    console.log('[Sidepanel] Full translate using model:', model);

    try {
        if (model === 'microsoft-translator') {
            await translateFullDocumentWithMicrosoft(currentProjectId);
        } else if (model === 'doubao-translation' || model === 'doubao-flash' || model === 'doubao-lite' ||
                   model === 'gemini-2.5-flash' || model === 'gemini-2.5-flash-lite' || model === 'gemini-3-pro') {
            await translateFullDocumentWithDoubao(currentProjectId, model);
        } else {
            throw new Error(`不支持的模型: ${model}`);
        }
    } catch (error) {
        console.error('[Sidepanel] Translation error:', error);
        showAIModelError(`翻译失败: ${error.message}`);
        document.getElementById('full-translate-btn').disabled = false;
        document.getElementById('translation-progress').style.display = 'none';
    }
});

// Reverse translate button handler (Chinese -> English)
document.getElementById('reverse-translate-btn').addEventListener('click', handleReverseTranslate);

// Reload English document button
document.getElementById('reload-english-btn').addEventListener('click', handleReloadEnglish);

// 切换当前文档按钮 - 获取Overleaf当前打开的文件名，如果与中文文档不同则切换
document.getElementById('refresh-zh-doc-btn').addEventListener('click', handleSwitchToCurrentDocument);

async function handleSwitchToCurrentDocument() {
    try {
        const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
        if (!tab || !tab.url || !tab.url.includes('overleaf.com')) {
            showError('请在 Overleaf 页面使用此功能');
            return;
        }

        // 从 Overleaf 获取当前真实的文件名
        const polledFilename = await getCurrentFilenameFromOverleaf(tab.id);

        if (!polledFilename) {
            showError('无法获取当前文档名称');
            return;
        }

        console.log('[Sidepanel] Switch document: Overleaf current file is', polledFilename);

        // 获取当前中文编辑器绑定的文件名
        const editorDiv = document.getElementById('zh-line-editor');
        const editorFileName = editorDiv?.dataset?.fileName;

        console.log('[Sidepanel] Switch document: Editor bound to', editorFileName);

        // 如果文件名相同，不需要切换
        if (polledFilename === editorFileName) {
            showSuccess('已是当前文档: ' + polledFilename);
            return;
        }

        // 文件名不同，需要切换
        showSuccess('正在切换到: ' + polledFilename, true);

        // 更新当前文件名
        currentFileName = polledFilename;

        // 暂停自动保存
        pauseAutoSave(5);

        // 检查文件类型（只有 .tex 和 .txt 支持边写边译）
        if (!isLiveTranslationFile(polledFilename)) {
            document.getElementById('zh-preview-status').textContent = '(不支持此文件类型)';
            document.getElementById('full-translate-btn').disabled = true;
            document.getElementById('reverse-translate-btn').disabled = true;
            document.getElementById('reload-english-btn').disabled = true;
            renderZhDocument('');
            showSuccess('当前文件类型不支持边写边译');
            return;
        }

        // 启用按钮
        document.getElementById('full-translate-btn').disabled = false;
        document.getElementById('reverse-translate-btn').disabled = false;
        document.getElementById('reload-english-btn').disabled = false;

        // 加载中文文档
        await fetchZhDocument(tab.id);

        showSuccess('已切换到: ' + polledFilename);
    } catch (error) {
        console.error('[Sidepanel] Switch document error:', error);
        showError('切换失败: ' + error.message);
    }
}

// =================== 消息监听器 ===================
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.type === 'CONTENT_UPDATE_NOTIFICATION') {
        // 内容更新通知只更新 currentContent，不会重新初始化边写边译
        // 因为 updateContent 中已经通过 liveTranslationInitialized 标记避免重复初始化
        console.log('[Sidepanel] Received content update notification');
        requestContent();
    } else if (request.type === 'SELECTION_UPDATE') {
        console.log('[Sidepanel] Received selection update:', request.selectedText?.substring(0, 50));
        selectedText = request.selectedText || '';
        selectedTextSource = request.source || '';
        updateTranslationButtons();
    } else if (request.type === 'FILE_CHANGED') {
        // 文件切换事件：仅记录日志，不做处理
        // 文件切换完全由轮询机制处理，避免事件和轮询的竞态条件
        console.log('[Sidepanel] FILE_CHANGED event received (ignored, handled by polling):', request.fileName);
    } else if (request.type === 'DOC_LINE_CHANGED') {
        // 处理来自 Overleaf 的行变化事件
        console.log('[Sidepanel] Doc line changed:', request);

        // 只有在首页时才处理（边写边译功能现在在首页）
        if (currentPageId !== 'home-page') {
            return;
        }

        // 检查来源：如果是从中文编辑器发起的操作，跳过（防止回环）
        if (request.source === 'zh-editor') {
            console.log('[Sidepanel] Ignoring DOC_LINE_CHANGED - source is zh-editor (preventing loop)');
            return;
        }

        // 检查请求中的文件名是否与编辑器绑定的文件匹配
        // 关键：使用编辑器上记录的文件名，而不是全局的 currentFileName
        // 这样可以避免文件切换时的竞态条件
        const editorDiv = document.getElementById('zh-line-editor');
        const editorFileName = editorDiv?.dataset?.fileName;

        if (!request.fileName) {
            console.log('[Sidepanel] Ignoring DOC_LINE_CHANGED - no fileName in request');
            return;
        }
        if (!editorFileName) {
            console.log('[Sidepanel] Ignoring DOC_LINE_CHANGED - editor not bound to any file');
            return;
        }
        if (request.fileName !== editorFileName) {
            console.log('[Sidepanel] Ignoring DOC_LINE_CHANGED - file mismatch:', request.fileName, '!= editor:', editorFileName);
            return;
        }

        const { changeType, lineNumber, count, insertType, deleteType, mergeToLine, prevLineNumber, currentLineNumber } = request;

        // 检查行号是否合理（负数或异常大的数字说明是文件切换导致的错误事件）
        if (prevLineNumber !== undefined && prevLineNumber < 0) {
            console.log('[Sidepanel] Ignoring DOC_LINE_CHANGED - invalid prevLineNumber:', prevLineNumber);
            return;
        }
        if (lineNumber !== undefined && lineNumber < 0) {
            console.log('[Sidepanel] Ignoring DOC_LINE_CHANGED - invalid lineNumber:', lineNumber);
            return;
        }

        if (changeType === 'insert') {
            // 根据 insertType 判断如何处理
            if (insertType === 'middle') {
                // 行中回车：需要翻译更新两行（使用 prevLineNumber 和 currentLineNumber）
                handleMiddleInsert(prevLineNumber, currentLineNumber);
            } else if (insertType === 'start') {
                // 行首回车：在当前行前面插入新行
                // prevLineNumber 是新插入的空行，currentLineNumber 是原来的行
                // 需要在 prevLineNumber - 1 之后插入
                insertZhDocumentLines(prevLineNumber - 1, count);
            } else {
                // 行尾回车 (end)：在当前行后面插入新行
                // prevLineNumber 是原来的行，currentLineNumber 是新插入的空行
                // 需要在 prevLineNumber 之后插入
                insertZhDocumentLines(prevLineNumber, count);
            }
        } else if (changeType === 'delete') {
            if (deleteType === 'merge') {
                // 行首 Backspace：合并下一行内容到当前行，然后删除下一行
                mergeZhDocumentLines(mergeToLine, lineNumber);
            } else {
                // 普通删除
                deleteZhDocumentLines(lineNumber, count);
            }
        }
    } else if (request.type === 'CURSOR_LINE_CHANGED') {
        // 处理光标行变化事件 - 同步滚动中文文档预览
        // 只有在首页时才处理（边写边译功能现在在首页）
        if (currentPageId === 'home-page') {
            // 在简略视图模式下，如果用户正在编辑中文文档，不要进行滚动同步
            // 这样用户可以专注于编辑而不被 Overleaf 的光标变化干扰
            if (isCompactMode) {
                const editorDiv = document.getElementById('zh-line-editor');
                const activeElement = document.activeElement;
                // 如果焦点在编辑器内，不进行滚动
                if (editorDiv && editorDiv.contains(activeElement)) {
                    return;
                }
            }
            scrollZhDocumentToLine(request.lineNumber);
        }
    } else if (request.type === 'COMPACT_VIEW_MESSAGE') {
        // 处理来自简略视图的消息
        if (typeof handleCompactViewMessage === 'function') {
            handleCompactViewMessage(request);
        }
    } else if (request.type === 'WENZHIYUN_FIX_COMPILE_ERROR') {
        // 处理文智云修复编译错误请求
        console.log('[Sidepanel] Received 文智云修复 request:', request.data);

        // 异步处理，需要返回 true 保持通道开放
        (async () => {
            try {
                const { errorInfo, currentFile, currentContent, compileLog } = request.data;

                // 将文件内容按行分割，构建氛围写作格式的 JSON
                const lines = currentContent.split('\n');
                const linesData = {};
                lines.forEach((line, index) => {
                    linesData[(index + 1).toString()] = line;
                });

                // 构建代码引用数据（与氛围写作完全一致的格式）
                const codeRefData = {};
                codeRefData[currentFile] = linesData;
                const codeRefJson = JSON.stringify(codeRefData, null, 2);

                // 构建简短的问题描述 prompt（附加在代码引用后面）
                const errorDescription = `

请帮我修复以下 LaTeX 编译错误：
错误: ${errorInfo.message || errorInfo.rawContent || '编译失败'}
${errorInfo.file ? `文件: ${errorInfo.file}` : ''}
${errorInfo.line ? `行号: ${errorInfo.line}` : ''}

编译日志:
${compileLog.substring(0, 1500)}${compileLog.length > 1500 ? '...' : ''}`;

                // 完整消息 = 代码引用 JSON + 问题描述
                const userMessage = codeRefJson + errorDescription;

                console.log('[Sidepanel] 文智云修复 sending message length:', userMessage.length);

                // 调用氛围写作 API（与 sendMessage 完全一致的方式）
                const response = await fetch(`${BACKEND_API_URL}/api/chat/ambient`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    credentials: 'include',
                    body: JSON.stringify({
                        message: userMessage,
                        history: [],
                        images: []
                    })
                });

                if (!response.ok) {
                    const errorData = await response.json().catch(() => ({}));
                    throw new Error(errorData.detail || `请求失败: ${response.status}`);
                }

                const result = await response.json();
                console.log('[Sidepanel] 文智云修复 API response:', result);

                // 使用氛围写作的解析函数解析响应
                if (typeof parseAmbientResponse === 'function') {
                    const parsed = parseAmbientResponse(result.reply);

                    // 如果有编辑指令，使用氛围写作的 processEdits 处理
                    if (parsed.edits && parsed.edits.length > 0 && typeof processEdits === 'function') {
                        await processEdits(parsed.edits);
                    }

                    // 显示消息（如果有）
                    if (parsed.message) {
                        showSuccess('修复建议: ' + parsed.message.substring(0, 100) + (parsed.message.length > 100 ? '...' : ''));
                    }
                }

                sendResponse({ success: true });

            } catch (error) {
                console.error('[Sidepanel] 文智云修复 error:', error);
                showAIModelError('修复失败: ' + error.message);
                sendResponse({ success: false, error: error.message });
            }
        })();

        return true; // 保持消息通道开放
    } else if (request.type === 'AUTO_CITE_SHORTCUT') {
        // Handle auto-cite shortcut - search papers and let user select
        console.log('[Sidepanel] Auto-cite shortcut triggered');

        // Use text from message if available, otherwise use stored selectedText
        const textForSearch = request.selectedText || selectedText;

        // Wait a bit for UI to be ready, then trigger
        setTimeout(async () => {
            if (textForSearch && textForSearch.trim()) {
                // Switch to auto-cite work page
                resetAutoCitePage();
                showPage('autocite-page');

                try {
                    // Step 1: Get keywords from backend
                    const keywordsResponse = await fetch(`${BACKEND_API_URL}/api/papers/keywords`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        credentials: 'include',
                        body: JSON.stringify({ text: textForSearch })
                    });

                    if (!keywordsResponse.ok) {
                        const errorData = await keywordsResponse.json().catch(() => ({}));
                        throw new Error(errorData.detail || `关键词提取失败: ${keywordsResponse.status}`);
                    }

                    const keywordsData = await keywordsResponse.json();
                    const keywords = keywordsData.keywords;

                    console.log('[Sidepanel] Extracted keywords:', keywords);

                    // Display keywords in input and hidden field
                    document.getElementById('autocite-keywords').textContent = keywords;
                    document.getElementById('autocite-keywords-input').value = keywords;
                    document.getElementById('autocite-keywords-display').textContent = `检索关键词: ${keywords}`;

                    // Step 2: Search papers with extracted keywords
                    await searchPapersWithKeywords(keywords);

                } catch (error) {
                    console.error('[Sidepanel] Auto-cite search error:', error);
                    showError('搜索论文失败: ' + error.message);
                    goToHomePage();
                }
            } else {
                showError('请先选中需要引用的文本');
            }
        }, 100);
    } else if (request.type === 'CONTINUE_WRITING_REQUEST') {
        // 处理续写请求（来自编辑器中的"续"按钮）
        console.log('[Sidepanel] Received continue writing request, content length:', request.contentBeforeCursor?.length);

        (async () => {
            try {
                // 获取续写设置
                const model = await getSelectedContinueWritingModel();
                const length = await getContinueWritingLength();
                const reasoningEffort = getContinueWritingReasoningEffort(model);

                console.log('[Sidepanel] Continue writing with model:', model, 'length:', length, 'reasoning_effort:', reasoningEffort);

                const result = await callContinueWritingAPI(request.contentBeforeCursor, model, length);

                if (result.success) {
                    // 更新用户 token 显示
                    if (result.remaining_tokens !== undefined && typeof updateUserTokensDisplay === 'function') {
                        updateUserTokensDisplay(result.remaining_tokens);
                    }
                    sendResponse({
                        success: true,
                        continuation: result.continuation
                    });
                } else {
                    sendResponse({
                        success: false,
                        error: result.error || '续写失败'
                    });
                }
            } catch (error) {
                console.error('[Sidepanel] Continue writing error:', error);
                sendResponse({
                    success: false,
                    error: error.message || '续写请求失败'
                });
            }
        })();

        return true; // 保持消息通道开放
    } else if (request.type === 'GET_CONTINUE_WRITING_ENABLED') {
        // 获取续写开关状态
        (async () => {
            try {
                const enabled = await isContinueWritingEnabled();
                sendResponse({ enabled: enabled });
            } catch (error) {
                console.error('[Sidepanel] Get continue writing enabled error:', error);
                sendResponse({ enabled: false });
            }
        })();

        return true; // 保持消息通道开放
    }
});

/**
 * Get advanced search options from UI
 * @returns {object} { sort, yearFrom, yearTo }
 */
function getAdvancedSearchOptions() {
    const sortSelect = document.getElementById('autocite-sort');
    const yearFromInput = document.getElementById('autocite-year-from');
    const yearToInput = document.getElementById('autocite-year-to');

    return {
        sort: sortSelect ? sortSelect.value : 'is-referenced-by-count',
        yearFrom: yearFromInput ? yearFromInput.value.trim() : '',
        yearTo: yearToInput ? yearToInput.value.trim() : ''
    };
}

/**
 * Search papers from CrossRef API with given keywords
 * @param {string} keywords - Search keywords
 * @param {object} options - Optional search options { sort, yearFrom, yearTo }
 */
async function searchPapersWithKeywords(keywords, options = null) {
    if (!keywords || !keywords.trim()) {
        showError('请输入搜索关键词');
        return;
    }

    // Get options from UI if not provided
    const searchOptions = options || getAdvancedSearchOptions();

    // Show loading state
    document.getElementById('autocite-loading').style.display = 'block';
    document.getElementById('autocite-selection').style.display = 'none';
    document.getElementById('autocite-keywords-display').textContent = `检索关键词: ${keywords}`;

    // Clear previous selection
    selectedPapers = [];
    document.getElementById('selected-count').textContent = '0';

    try {
        // Search CrossRef API directly from frontend
        const crossrefUrl = new URL('https://api.crossref.org/works');
        crossrefUrl.searchParams.set('query', keywords);
        crossrefUrl.searchParams.set('rows', '30');
        crossrefUrl.searchParams.set('select', 'DOI,title,author,published,container-title,type,is-referenced-by-count');

        // Build filter string
        const filters = ['type:journal-article,type:proceedings-article'];

        // Add year range filter if specified
        if (searchOptions.yearFrom) {
            filters.push(`from-pub-date:${searchOptions.yearFrom}`);
        }
        if (searchOptions.yearTo) {
            filters.push(`until-pub-date:${searchOptions.yearTo}`);
        }

        crossrefUrl.searchParams.set('filter', filters.join(','));

        // Add sort parameter (only if not sorting by citation count, which we do client-side)
        if (searchOptions.sort && searchOptions.sort !== 'is-referenced-by-count') {
            crossrefUrl.searchParams.set('sort', searchOptions.sort);
            crossrefUrl.searchParams.set('order', 'desc');
        }

        console.log('[Sidepanel] CrossRef URL:', crossrefUrl.toString());

        const crossrefResponse = await fetch(crossrefUrl.toString(), {
            method: 'GET',
            headers: {
                'Accept': 'application/json'
            }
        });

        if (!crossrefResponse.ok) {
            throw new Error(`CrossRef搜索失败: ${crossrefResponse.status}`);
        }

        const crossrefData = await crossrefResponse.json();
        const items = crossrefData.message?.items || [];

        // Sort based on user selection (only for citation count, others are sorted by API)
        if (searchOptions.sort === 'is-referenced-by-count') {
            items.sort((a, b) => (b['is-referenced-by-count'] || 0) - (a['is-referenced-by-count'] || 0));
        }
        // For 'published' and 'relevance', the API already returns sorted results

        // Format papers for display
        const papers = items.map(item => {
            // Extract authors
            const authors = (item.author || []).map(author => {
                const family = author.family || '';
                const given = author.given || '';
                if (family && given) {
                    return `${given} ${family}`;
                }
                return family || given || '';
            }).filter(name => name);

            // Extract year
            const dateparts = item.published?.['date-parts']?.[0] || [];
            const year = dateparts[0] || 'N/A';

            // Get citation count
            const citationCount = item['is-referenced-by-count'] || 0;

            return {
                doi: item.DOI || '',
                title: (item.title && item.title[0]) || 'No title',
                authors: authors,
                year: year,
                journal: (item['container-title'] && item['container-title'][0]) || '',
                type: item.type || 'article',
                citationCount: citationCount
            };
        });

        console.log('[Sidepanel] Found', papers.length, 'papers from CrossRef');

        if (papers.length > 0) {
            // Display paper list
            const paperList = document.getElementById('paper-list');
            paperList.innerHTML = '';

            for (const paper of papers) {
                const paperItem = document.createElement('div');
                paperItem.className = 'paper-item';
                paperItem.paperData = paper;

                // 生成 BibTeX
                const firstAuthor = paper.authors[0] || 'Unknown';
                const lastName = firstAuthor.split(' ').pop();
                const citationKey = `${lastName}${paper.year}`.replace(/[^a-zA-Z0-9]/g, '');
                const bibEntry = `@article{${citationKey},
  title={${paper.title}},
  author={${paper.authors.join(' and ')}},
  journal={${paper.journal}},
  year={${paper.year}},
  doi={${paper.doi}}
}`;

                paperItem.innerHTML = `
                    <div class="paper-checkbox">
                        <input type="checkbox" class="paper-select">
                    </div>
                    <div class="paper-info">
                        <div class="paper-title">${paper.title}</div>
                        <div class="paper-authors">${paper.authors.join(', ')}</div>
                        <div class="paper-meta">${paper.journal} · ${paper.year} · 引用: ${paper.citationCount}</div>
                    </div>
                    <button class="paper-copy-bib-btn" title="复制 BibTeX">
                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
                        </svg>
                        复制BIB
                    </button>
                `;

                // 存储 bibEntry 供复制使用
                paperItem.bibEntry = bibEntry;

                // Handle checkbox change
                const checkbox = paperItem.querySelector('.paper-select');
                paperItem.addEventListener('click', (e) => {
                    // 排除复制按钮的点击
                    if (e.target !== checkbox && !e.target.closest('.paper-copy-bib-btn')) {
                        checkbox.checked = !checkbox.checked;
                        togglePaperSelection(paperItem, checkbox.checked);
                    }
                });

                checkbox.addEventListener('change', (e) => {
                    togglePaperSelection(paperItem, e.target.checked);
                });

                // Handle copy bib button click
                const copyBibBtn = paperItem.querySelector('.paper-copy-bib-btn');
                copyBibBtn.addEventListener('click', async (e) => {
                    e.stopPropagation();
                    try {
                        await navigator.clipboard.writeText(bibEntry);
                        showSuccess('BibTeX 已复制到剪贴板！');
                        // 按钮短暂变色反馈
                        copyBibBtn.classList.add('copied');
                        setTimeout(() => copyBibBtn.classList.remove('copied'), 1500);
                    } catch (err) {
                        console.error('复制失败:', err);
                        showError('复制失败，请手动选择复制');
                    }
                });

                paperList.appendChild(paperItem);
            }

            document.getElementById('autocite-loading').style.display = 'none';
            document.getElementById('autocite-selection').style.display = 'block';
        } else {
            document.getElementById('autocite-loading').style.display = 'none';
            document.getElementById('autocite-selection').style.display = 'block';
            document.getElementById('paper-list').innerHTML = '<p class="text-center text-slate-500 py-8">未找到相关论文，请尝试修改关键词</p>';
        }
    } catch (error) {
        console.error('[Sidepanel] CrossRef search error:', error);
        document.getElementById('autocite-loading').style.display = 'none';
        document.getElementById('autocite-selection').style.display = 'block';
        document.getElementById('paper-list').innerHTML = `<p class="text-center text-red-500 py-8">搜索失败: ${error.message}</p>`;
    }
}

/**
 * Handle re-search button click
 */
function handleAutoCiteResearch() {
    const keywordsInput = document.getElementById('autocite-keywords-input');
    const keywords = keywordsInput.value.trim();

    if (keywords) {
        console.log('[Sidepanel] Re-searching with keywords:', keywords);
        searchPapersWithKeywords(keywords);
    } else {
        showError('请输入搜索关键词');
    }
}

// Initialize re-search button event
document.addEventListener('DOMContentLoaded', () => {
    const researchBtn = document.getElementById('autocite-research-btn');
    if (researchBtn) {
        researchBtn.addEventListener('click', handleAutoCiteResearch);
    }

    // Also handle Enter key in keywords input
    const keywordsInput = document.getElementById('autocite-keywords-input');
    if (keywordsInput) {
        keywordsInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') {
                e.preventDefault();
                handleAutoCiteResearch();
            }
        });
    }
});

// Show extension is ready
console.log('[Sidepanel] Overleaf Document Reader sidepanel loaded');
