// This script will be injected into the page context to access the editor
(function() {
    'use strict';

    // 防止重复初始化
    if (window.__overleafReaderInjectedInitialized) {
        console.log('[Overleaf Reader Injected] Already initialized, skipping');
        return;
    }
    window.__overleafReaderInjectedInitialized = true;

    console.log('[Overleaf Reader Injected] Script loaded in page context');

    // Simple diff algorithm to calculate incremental changes
    function calculateDiff(oldText, newText) {
        console.log('[Overleaf Reader Injected] Calculating diff, old length:', oldText?.length ?? 0, 'new length:', newText?.length ?? 0);

        // If no original content or empty string, do full replacement
        if (oldText === null || oldText === undefined || oldText === '') {
            console.log('[Overleaf Reader Injected] Empty or null old text, doing full replacement');
            return [{
                from: 0,
                to: 0,
                insert: newText
            }];
        }

        // If texts are identical, no changes needed
        if (oldText === newText) {
            console.log('[Overleaf Reader Injected] No changes detected');
            return [];
        }

        // Find common prefix
        let prefixLength = 0;
        const minLength = Math.min(oldText.length, newText.length);
        while (prefixLength < minLength && oldText[prefixLength] === newText[prefixLength]) {
            prefixLength++;
        }

        // Find common suffix
        let suffixLength = 0;
        const oldSuffixStart = oldText.length - 1;
        const newSuffixStart = newText.length - 1;
        while (suffixLength < minLength - prefixLength &&
               oldText[oldSuffixStart - suffixLength] === newText[newSuffixStart - suffixLength]) {
            suffixLength++;
        }

        // Calculate the range to replace
        const from = prefixLength;
        const to = oldText.length - suffixLength;
        const insert = newText.slice(prefixLength, newText.length - suffixLength);

        console.log('[Overleaf Reader Injected] Diff calculated - from:', from, 'to:', to, 'insert length:', insert.length);

        // If the change is very small compared to document size, use incremental update
        const changeRatio = Math.abs(to - from) / oldText.length;
        const insertRatio = insert.length / newText.length;

        console.log('[Overleaf Reader Injected] Change ratio:', changeRatio, 'Insert ratio:', insertRatio);

        // Use incremental update if change is less than 50% of document
        if (changeRatio < 0.5 && insertRatio < 0.8) {
            return [{
                from: from,
                to: to,
                insert: insert
            }];
        } else {
            // For large changes, fall back to full replacement
            console.log('[Overleaf Reader Injected] Large change detected, using full replacement');
            return [{
                from: 0,
                to: oldText.length,
                insert: newText
            }];
        }
    }

    // Create a function to jump to a specific line
    window.__overleafReaderJumpToLine = function(lineNumber) {
        console.log('[Overleaf Reader Injected] Attempting to jump to line:', lineNumber);

        // Method 1: Use Overleaf's official store API
        try {
            if (window.overleaf && window.overleaf.unstable && window.overleaf.unstable.store) {
                const view = window.overleaf.unstable.store.get('editor.view');
                if (view && view.state && view.state.doc) {
                    console.log('[Overleaf Reader Injected] Found editor view via overleaf store');

                    const doc = view.state.doc;
                    if (lineNumber > doc.lines) {
                        console.log('[Overleaf Reader Injected] Line number out of range:', lineNumber, 'max:', doc.lines);
                        return false;
                    }

                    const line = doc.line(lineNumber);
                    const pos = line.from;

                    view.dispatch({
                        selection: { anchor: pos, head: pos },
                        scrollIntoView: true
                    });

                    view.focus();
                    console.log('[Overleaf Reader Injected] Successfully jumped to line:', lineNumber, 'position:', pos);
                    return true;
                }
            }
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error with overleaf store API:', e);
        }

        // Method 2: Use the stored editor view if available
        if (window.__overleafEditorView) {
            try {
                const view = window.__overleafEditorView;
                const doc = view.state.doc;

                if (lineNumber > doc.lines) {
                    console.log('[Overleaf Reader Injected] Line number out of range:', lineNumber, 'max:', doc.lines);
                    return false;
                }

                const line = doc.line(lineNumber);
                const pos = line.from;

                view.dispatch({
                    selection: { anchor: pos, head: pos },
                    scrollIntoView: true
                });

                view.focus();
                console.log('[Overleaf Reader Injected] Successfully jumped to line:', lineNumber, 'position:', pos);
                return true;
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error jumping with stored view:', e);
            }
        }

        // Method 2: Try to find CodeMirror editor and jump
        const editors = document.querySelectorAll('.cm-editor');
        console.log('[Overleaf Reader Injected] Found', editors.length, 'cm-editor elements');

        for (let i = 0; i < editors.length; i++) {
            const editor = editors[i];
            console.log('[Overleaf Reader Injected] Checking editor', i, editor);

            let view = null;

            // Try different ways to get the view
            if (editor.cmView) {
                view = editor.cmView;
                console.log('[Overleaf Reader Injected] Found view via cmView');
            } else if (editor._view) {
                view = editor._view;
                console.log('[Overleaf Reader Injected] Found view via _view');
            }

            // Check content element
            if (!view) {
                const content = editor.querySelector('.cm-content');
                if (content) {
                    if (content.cmView) {
                        view = content.cmView;
                        console.log('[Overleaf Reader Injected] Found view via content.cmView');
                    } else if (content._view) {
                        view = content._view;
                        console.log('[Overleaf Reader Injected] Found view via content._view');
                    }
                }
            }

            // Try React Fiber
            if (!view) {
                const keys = Object.keys(editor);
                const reactKey = keys.find(key => key.startsWith('__reactInternalInstance') || key.startsWith('__reactFiber'));
                if (reactKey) {
                    try {
                        let fiber = editor[reactKey];
                        let searchCount = 0;
                        while (fiber && searchCount < 20) {
                            if (fiber.memoizedProps && fiber.memoizedProps.view) {
                                view = fiber.memoizedProps.view;
                                console.log('[Overleaf Reader Injected] Found view via React fiber props');
                                break;
                            }
                            if (fiber.stateNode && fiber.stateNode.view) {
                                view = fiber.stateNode.view;
                                console.log('[Overleaf Reader Injected] Found view via React fiber stateNode');
                                break;
                            }
                            fiber = fiber.return || fiber.child;
                            searchCount++;
                        }
                    } catch (e) {
                        console.log('[Overleaf Reader Injected] Error accessing React fiber:', e);
                    }
                }
            }

            console.log('[Overleaf Reader Injected] View object:', view);

            if (view) {
                console.log('[Overleaf Reader Injected] View state:', view.state);

                if (view.state) {
                    console.log('[Overleaf Reader Injected] View state doc:', view.state.doc);

                    if (view.state.doc) {
                        try {
                            const doc = view.state.doc;
                            console.log('[Overleaf Reader Injected] Found valid view, doc has', doc.lines, 'lines');

                            if (lineNumber > doc.lines) {
                                console.log('[Overleaf Reader Injected] Line number out of range:', lineNumber, 'max:', doc.lines);
                                continue;
                            }

                            const line = doc.line(lineNumber);
                            const pos = line.from;

                            console.log('[Overleaf Reader Injected] Jumping to line', lineNumber, 'position', pos);

                            view.dispatch({
                                selection: { anchor: pos, head: pos },
                                scrollIntoView: true
                            });

                            view.focus();
                            console.log('[Overleaf Reader Injected] Successfully jumped to line:', lineNumber);
                            return true;
                        } catch (e) {
                            console.error('[Overleaf Reader Injected] Error jumping to line:', e);
                        }
                    } else {
                        console.log('[Overleaf Reader Injected] No doc in view.state for editor', i);
                    }
                } else {
                    console.log('[Overleaf Reader Injected] No state in view for editor', i);
                }
            } else {
                console.log('[Overleaf Reader Injected] No view found for editor', i);
            }
        }

        // Method 3: Try using Ctrl+G as fallback
        console.log('[Overleaf Reader Injected] Trying Ctrl+G fallback method');
        try {
            const editorArea = document.querySelector('.cm-editor, .ace_editor');
            if (editorArea) {
                editorArea.focus();

                // Simulate Ctrl+G
                const ctrlG = new KeyboardEvent('keydown', {
                    key: 'g',
                    code: 'KeyG',
                    ctrlKey: true,
                    bubbles: true,
                    cancelable: true
                });

                editorArea.dispatchEvent(ctrlG);

                // Wait a bit then try to input the line number
                setTimeout(() => {
                    const goToDialog = document.querySelector('input[placeholder*="line"], input[placeholder*="Line"], .modal input, .dialog input');
                    if (goToDialog) {
                        goToDialog.value = lineNumber.toString();
                        goToDialog.dispatchEvent(new Event('input', { bubbles: true }));

                        // Press Enter
                        setTimeout(() => {
                            const enterEvent = new KeyboardEvent('keydown', {
                                key: 'Enter',
                                code: 'Enter',
                                bubbles: true,
                                cancelable: true
                            });
                            goToDialog.dispatchEvent(enterEvent);
                            console.log('[Overleaf Reader Injected] Used Ctrl+G fallback method');
                        }, 100);
                    }
                }, 200);

                return true; // We tried our best
            }
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error with Ctrl+G fallback:', e);
        }

        console.log('[Overleaf Reader Injected] No suitable editor found for jumping');
        return false;
    };

    // Create a function to update editor content
    window.__overleafReaderUpdateContent = function(newContent, originalContent) {
        console.log('[Overleaf Reader Injected] Attempting to update content, length:', newContent.length);

        // Method 1: Use Overleaf's official store API
        try {
            if (window.overleaf && window.overleaf.unstable && window.overleaf.unstable.store) {
                const view = window.overleaf.unstable.store.get('editor.view');
                if (view && view.state && view.state.doc) {
                    console.log('[Overleaf Reader Injected] Found editor view via overleaf store for update');

                    const doc = view.state.doc;
                    const currentContent = doc.toString();

                    // IMPORTANT: If current document is empty, always use empty string as diffBase
                    // Otherwise, calculateDiff might generate invalid ranges (e.g., from 0 to X in a doc of length 0)
                    let diffBase;
                    if (currentContent === '') {
                        console.log('[Overleaf Reader Injected] Current document is empty, forcing diffBase to empty string');
                        diffBase = '';
                    } else {
                        // Use the provided original content or current content for diff
                        diffBase = (originalContent !== undefined && originalContent !== null) ? originalContent : currentContent;
                    }

                    console.log('[Overleaf Reader Injected] DiffBase length:', diffBase.length, 'Current content length:', currentContent.length);

                    // Calculate incremental changes
                    const changes = calculateDiff(diffBase, newContent);

                    if (changes.length === 0) {
                        console.log('[Overleaf Reader Injected] No changes to apply');
                        return true;
                    }

                    // Apply the changes
                    view.dispatch({ changes: changes });

                    view.focus();
                    console.log('[Overleaf Reader Injected] Successfully updated content with incremental changes:', changes.length, 'operations');
                    return true;
                }
            }
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error with overleaf store API update:', e);
        }

        // Method 2: Use the stored editor view if available
        if (window.__overleafEditorView) {
            try {
                const view = window.__overleafEditorView;
                const doc = view.state.doc;
                const currentContent = doc.toString();

                // IMPORTANT: If current document is empty, always use empty string as diffBase
                // Otherwise, calculateDiff might generate invalid ranges (e.g., from 0 to X in a doc of length 0)
                let diffBase;
                if (currentContent === '') {
                    console.log('[Overleaf Reader Injected] (Stored view) Current document is empty, forcing diffBase to empty string');
                    diffBase = '';
                } else {
                    // Use the provided original content or current content for diff
                    diffBase = (originalContent !== undefined && originalContent !== null) ? originalContent : currentContent;
                }

                console.log('[Overleaf Reader Injected] (Stored view) DiffBase length:', diffBase.length, 'Current content length:', currentContent.length);

                // Calculate incremental changes
                const changes = calculateDiff(diffBase, newContent);

                if (changes.length === 0) {
                    console.log('[Overleaf Reader Injected] No changes to apply (stored view)');
                    return true;
                }

                // Apply the changes
                view.dispatch({ changes: changes });

                view.focus();
                console.log('[Overleaf Reader Injected] Successfully updated content with stored view, incremental changes:', changes.length, 'operations');
                return true;
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error updating with stored view:', e);
            }
        }

        // Method 2: Try to find CodeMirror editor and update
        const editors = document.querySelectorAll('.cm-editor');
        console.log('[Overleaf Reader Injected] Found', editors.length, 'cm-editor elements for update');

        for (let i = 0; i < editors.length; i++) {
            const editor = editors[i];
            let view = null;

            // Try different ways to get the view
            if (editor.cmView) {
                view = editor.cmView;
            } else if (editor._view) {
                view = editor._view;
            }

            // Check content element
            if (!view) {
                const content = editor.querySelector('.cm-content');
                if (content) {
                    if (content.cmView) {
                        view = content.cmView;
                    } else if (content._view) {
                        view = content._view;
                    }
                }
            }

            // Try React Fiber
            if (!view) {
                const keys = Object.keys(editor);
                const reactKey = keys.find(key => key.startsWith('__reactInternalInstance') || key.startsWith('__reactFiber'));
                if (reactKey) {
                    try {
                        let fiber = editor[reactKey];
                        let searchCount = 0;
                        while (fiber && searchCount < 20) {
                            if (fiber.memoizedProps && fiber.memoizedProps.view) {
                                view = fiber.memoizedProps.view;
                                break;
                            }
                            if (fiber.stateNode && fiber.stateNode.view) {
                                view = fiber.stateNode.view;
                                break;
                            }
                            fiber = fiber.return || fiber.child;
                            searchCount++;
                        }
                    } catch (e) {
                        console.log('[Overleaf Reader Injected] Error accessing React fiber for update:', e);
                    }
                }
            }

            if (view && view.state && view.state.doc) {
                try {
                    const doc = view.state.doc;

                    // Replace entire document content
                    view.dispatch({
                        changes: {
                            from: 0,
                            to: doc.length,
                            insert: newContent
                        }
                    });

                    view.focus();
                    console.log('[Overleaf Reader Injected] Successfully updated content for editor', i);
                    return true;
                } catch (e) {
                    console.error('[Overleaf Reader Injected] Error updating content for editor', i, ':', e);
                }
            }
        }

        console.log('[Overleaf Reader Injected] No suitable editor found for updating');
        return false;
    };

    // 精确删除指定行
    window.__overleafReaderDeleteLine = function(lineNumber) {
        console.log('[Overleaf Reader Injected] Deleting line:', lineNumber);

        // 获取 editor view
        const view = window.overleaf?.unstable?.store?.get('editor.view');
        if (view && view.state && view.state.doc) {
            try {
                const doc = view.state.doc;
                const totalLines = doc.lines;

                if (lineNumber < 1 || lineNumber > totalLines) {
                    console.log('[Overleaf Reader Injected] Line number out of range:', lineNumber, 'total:', totalLines);
                    return false;
                }

                const line = doc.line(lineNumber);
                let from = line.from;
                let to = line.to;

                // 如果不是最后一行，删除包括换行符
                if (lineNumber < totalLines) {
                    to = doc.line(lineNumber + 1).from;
                } else if (lineNumber > 1) {
                    // 如果是最后一行，删除前面的换行符
                    from = doc.line(lineNumber - 1).to;
                }

                view.dispatch({
                    changes: { from, to, insert: '' }
                });

                console.log('[Overleaf Reader Injected] Successfully deleted line:', lineNumber);
                return true;
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error deleting line:', e);
                return false;
            }
        }

        console.log('[Overleaf Reader Injected] No editor view found for delete');
        return false;
    };

    // 合并行：将 fromLineNumber 行合并到 toLineNumber 行末尾，然后删除 fromLineNumber 行
    window.__overleafReaderMergeLines = function(toLineNumber, fromLineNumber) {
        console.log('[Overleaf Reader Injected] Merging line', fromLineNumber, 'into line', toLineNumber);

        const view = window.overleaf?.unstable?.store?.get('editor.view');
        if (view && view.state && view.state.doc) {
            try {
                const doc = view.state.doc;
                const totalLines = doc.lines;

                if (toLineNumber < 1 || toLineNumber > totalLines ||
                    fromLineNumber < 1 || fromLineNumber > totalLines) {
                    console.log('[Overleaf Reader Injected] Line number out of range');
                    return false;
                }

                const toLine = doc.line(toLineNumber);
                const fromLine = doc.line(fromLineNumber);

                // 删除 toLine 行末尾到 fromLine 行开头之间的换行符（实现合并）
                // 这实际上就是删除从 toLine.to 到 fromLine.from 的内容
                const from = toLine.to;
                const to = fromLine.from;

                view.dispatch({
                    changes: { from, to, insert: '' }
                });

                console.log('[Overleaf Reader Injected] Successfully merged lines');
                return true;
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error merging lines:', e);
                return false;
            }
        }

        console.log('[Overleaf Reader Injected] No editor view found for merge');
        return false;
    };

    // 在指定行后插入新行
    window.__overleafReaderInsertLineAfter = function(afterLineNumber) {
        console.log('[Overleaf Reader Injected] Inserting line after:', afterLineNumber);

        // 获取 editor view
        const view = window.overleaf?.unstable?.store?.get('editor.view');
        if (view && view.state && view.state.doc) {
            try {
                const doc = view.state.doc;
                const totalLines = doc.lines;

                if (afterLineNumber < 0 || afterLineNumber > totalLines) {
                    console.log('[Overleaf Reader Injected] Line number out of range:', afterLineNumber, 'total:', totalLines);
                    return false;
                }

                let insertPos;
                if (afterLineNumber === 0) {
                    // 插入到开头
                    insertPos = 0;
                } else {
                    // 插入到指定行的末尾
                    const line = doc.line(afterLineNumber);
                    insertPos = line.to;
                }

                view.dispatch({
                    changes: { from: insertPos, to: insertPos, insert: '\n' }
                });

                console.log('[Overleaf Reader Injected] Successfully inserted line after:', afterLineNumber);
                return true;
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error inserting line:', e);
                return false;
            }
        }

        console.log('[Overleaf Reader Injected] No editor view found for insert');
        return false;
    };

    // 计算行内 diff，只更新真正改变的部分
    function calculateLineDiff(oldLineText, newLineText, lineStartPos) {
        // 如果内容相同，无需更新
        if (oldLineText === newLineText) {
            console.log('[Overleaf Reader Injected] Line content unchanged, skipping');
            return null;
        }

        // 找到公共前缀
        let prefixLength = 0;
        const minLength = Math.min(oldLineText.length, newLineText.length);
        while (prefixLength < minLength && oldLineText[prefixLength] === newLineText[prefixLength]) {
            prefixLength++;
        }

        // 找到公共后缀
        let suffixLength = 0;
        const oldSuffixStart = oldLineText.length - 1;
        const newSuffixStart = newLineText.length - 1;
        while (suffixLength < minLength - prefixLength &&
               oldLineText[oldSuffixStart - suffixLength] === newLineText[newSuffixStart - suffixLength]) {
            suffixLength++;
        }

        // 计算需要替换的范围（相对于文档的位置）
        const from = lineStartPos + prefixLength;
        const to = lineStartPos + oldLineText.length - suffixLength;
        const insert = newLineText.slice(prefixLength, newLineText.length - suffixLength);

        console.log('[Overleaf Reader Injected] Line diff - prefix:', prefixLength, 'suffix:', suffixLength);
        console.log('[Overleaf Reader Injected] Line diff - from:', from, 'to:', to, 'insert:', insert.substring(0, 50));

        return { from, to, insert };
    }

    // 更新指定行的内容（使用 diff 只更新改变的部分）
    window.__overleafReaderUpdateLineContent = function(lineNumber, newContent) {
        console.log('[Overleaf Reader Injected] Updating line content:', lineNumber, newContent.substring(0, 50));

        // 获取 editor view
        const view = window.overleaf?.unstable?.store?.get('editor.view');
        if (view && view.state && view.state.doc) {
            try {
                const doc = view.state.doc;
                const totalLines = doc.lines;

                if (lineNumber < 1 || lineNumber > totalLines) {
                    console.log('[Overleaf Reader Injected] Line number out of range:', lineNumber, 'total:', totalLines);
                    return false;
                }

                const line = doc.line(lineNumber);
                const oldContent = line.text;
                const lineStartPos = line.from;

                // 使用 diff 计算只需要更新的部分
                const change = calculateLineDiff(oldContent, newContent, lineStartPos);

                if (change === null) {
                    // 内容相同，无需更新
                    console.log('[Overleaf Reader Injected] Line content unchanged, no update needed');
                    return true;
                }

                view.dispatch({
                    changes: change
                });

                console.log('[Overleaf Reader Injected] Successfully updated line:', lineNumber, 'with diff-based change');
                return true;
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error updating line content:', e);
                return false;
            }
        }

        console.log('[Overleaf Reader Injected] No editor view found for update');
        return false;
    };

    // Create a function to find and read editor content
    window.__overleafReaderGetContent = function() {
        console.log('[Overleaf Reader Injected] Searching for editor...');

        // Method 1: Use Overleaf's official store API
        try {
            if (window.overleaf && window.overleaf.unstable && window.overleaf.unstable.store) {
                const view = window.overleaf.unstable.store.get('editor.view');
                if (view && view.state && view.state.doc) {
                    console.log('[Overleaf Reader Injected] Found editor view via overleaf store for content');
                    const content = view.state.doc.toString();
                    console.log('[Overleaf Reader Injected] Found content via store API, length:', content.length);
                    return content;
                }
            }
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error with overleaf store API for content:', e);
        }

        // Method 2: Look for CodeMirror 6 editor elements
        const editors = document.querySelectorAll('.cm-editor');
        for (const editor of editors) {
            // Try to find the view through various paths
            let view = null;

            // Check direct properties
            if (editor.cmView) view = editor.cmView;
            else if (editor._view) view = editor._view;

            // Check through content element
            if (!view) {
                const content = editor.querySelector('.cm-content');
                if (content) {
                    if (content.cmView) view = content.cmView;
                    else if (content._view) view = content._view;
                }
            }

            // Try to get view from React Fiber
            if (!view) {
                const keys = Object.keys(editor);
                const reactKey = keys.find(key => key.startsWith('__reactInternalInstance') || key.startsWith('__reactFiber'));
                if (reactKey) {
                    try {
                        let fiber = editor[reactKey];
                        while (fiber) {
                            if (fiber.memoizedProps && fiber.memoizedProps.view) {
                                view = fiber.memoizedProps.view;
                                break;
                            }
                            if (fiber.stateNode && fiber.stateNode.view) {
                                view = fiber.stateNode.view;
                                break;
                            }
                            fiber = fiber.return || fiber.child;
                        }
                    } catch (e) {
                        console.log('[Overleaf Reader Injected] Error accessing React fiber:', e);
                    }
                }
            }

            if (view && view.state && view.state.doc) {
                try {
                    const content = view.state.doc.toString();
                    console.log('[Overleaf Reader Injected] Found content, length:', content.length);
                    return content;
                } catch (e) {
                    console.error('[Overleaf Reader Injected] Error reading content:', e);
                }
            }
        }

        // Method 2: Look for Ace editor (fallback for older projects)
        const aceEditors = document.querySelectorAll('.ace_editor');
        for (const aceEditor of aceEditors) {
            if (window.ace && aceEditor.id) {
                try {
                    const editor = window.ace.edit(aceEditor.id);
                    if (editor) {
                        const content = editor.getValue();
                        console.log('[Overleaf Reader Injected] Found Ace content, length:', content.length);
                        return content;
                    }
                } catch (e) {
                    console.log('[Overleaf Reader Injected] Error with Ace editor:', e);
                }
            }
        }

        return null;
    };

    // Try to hook into the editor when it's created
    if (window.UNSTABLE_editorHelp) {
        console.log('[Overleaf Reader Injected] Found UNSTABLE_editorHelp, editor might be available');
    }

    // Listen for the extensions event and try to add our plugin
    window.addEventListener('UNSTABLE_editor:extensions', function(evt) {
        console.log('[Overleaf Reader Injected] Extensions event captured');
        if (evt.detail && evt.detail.CodeMirror && evt.detail.extensions) {
            const { CodeMirror, extensions } = evt.detail;

            try {
                const contentPlugin = CodeMirror.ViewPlugin.define(view => {
                    console.log('[Overleaf Reader Injected] View plugin created');

                    // Store view globally for access
                    window.__overleafEditorView = view;

                    // Send initial content
                    const content = view.state.doc.toString();
                    window.postMessage({
                        type: 'OVERLEAF_READER_CONTENT',
                        content: content,
                        source: 'plugin'
                    }, '*');

                    // Track last cursor line to avoid duplicate messages
                    let lastCursorLine = -1;
                    let lastLineCount = -1;

                    return {
                        update(update) {
                            if (update.docChanged) {
                                const content = update.state.doc.toString();
                                const newLineCount = update.state.doc.lines;

                                // 注意：行变化检测已移至轮询机制，这里不再发送 OVERLEAF_LINES_INSERTED/DELETED
                                // 只更新 lastLineCount 用于追踪
                                lastLineCount = newLineCount;

                                window.postMessage({
                                    type: 'OVERLEAF_READER_CONTENT',
                                    content: content,
                                    source: 'plugin-update'
                                }, '*');
                            }

                            // Check if selection/cursor changed
                            if (update.selectionSet || update.docChanged) {
                                try {
                                    const selection = update.state.selection.main;
                                    const cursorPos = selection.head;
                                    const line = update.state.doc.lineAt(cursorPos);
                                    const lineNumber = line.number;

                                    // Only send if line changed
                                    if (lineNumber !== lastCursorLine) {
                                        lastCursorLine = lineNumber;
                                        window.postMessage({
                                            type: 'OVERLEAF_CURSOR_LINE_CHANGED',
                                            lineNumber: lineNumber
                                        }, '*');
                                    }
                                } catch (e) {
                                    // Ignore errors
                                }
                            }
                        }
                    };
                });

                extensions.push(contentPlugin);
                console.log('[Overleaf Reader Injected] Plugin added to extensions');
            } catch (e) {
                console.error('[Overleaf Reader Injected] Error adding plugin:', e);
            }
        }
    });

    // Periodically check for content
    // Use faster interval initially to get content quickly on first load
    let periodicCheckCount = 0;
    const maxFastChecks = 20; // First 20 checks are fast (every 500ms = 10 seconds)

    const periodicContentCheck = () => {
        const content = window.__overleafReaderGetContent();
        if (content) {
            window.postMessage({
                type: 'OVERLEAF_READER_CONTENT',
                content: content,
                source: 'periodic'
            }, '*');
        }

        periodicCheckCount++;
        // Use 500ms interval for first 20 checks, then switch to 3000ms
        const nextInterval = periodicCheckCount < maxFastChecks ? 500 : 3000;
        setTimeout(periodicContentCheck, nextInterval);
    };

    // Start the periodic check
    setTimeout(periodicContentCheck, 500);

    // Polling-based cursor position and line count monitor (fallback for when UNSTABLE_editor:extensions doesn't work)
    let lastPolledCursorLine = -1;
    let lastPolledLineCount = -1;
    let lastPolledFileName = null; // 用于检测文件切换

    // 使用时间戳来防止轮询检测到我们自己触发的变化
    let lastExternalUpdateTime = 0;
    const EXTERNAL_UPDATE_COOLDOWN = 1000; // 1秒冷却

    // 文件切换检测轮询
    setInterval(() => {
        try {
            const currentFile = window.__overleafReaderGetCurrentFile();
            if (currentFile && currentFile !== lastPolledFileName) {
                console.log('[Overleaf Reader Injected] File changed from', lastPolledFileName, 'to', currentFile);
                lastPolledFileName = currentFile;

                // 发送文件切换消息
                window.postMessage({
                    type: 'OVERLEAF_FILE_CHANGED',
                    fileName: currentFile
                }, '*');
            }
        } catch (e) {
            // Ignore errors in file polling
        }
    }, 500); // 每 500ms 检查一次文件切换

    setInterval(() => {
        try {
            // Try to get cursor position and line count from store API
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (view && view.state) {
                const doc = view.state.doc;
                const newLineCount = doc.lines;

                // Check for line count changes (insert/delete detection)
                // 使用时间戳检查而不是标志检查，因为标志可能在异步操作中被重置
                const timeSinceLastUpdate = Date.now() - lastExternalUpdateTime;
                const isExternalUpdate = window.__overleafReaderExternalUpdate || timeSinceLastUpdate < EXTERNAL_UPDATE_COOLDOWN;

                if (!isExternalUpdate && lastPolledLineCount !== -1 && newLineCount !== lastPolledLineCount) {
                    const selection = view.state.selection.main;
                    const cursorPos = selection.head;
                    const cursorLine = doc.lineAt(cursorPos).number;

                    if (newLineCount > lastPolledLineCount) {
                        // Lines inserted
                        const insertedCount = newLineCount - lastPolledLineCount;

                        // 获取当前行（光标所在的新行）和上一行的信息
                        const currentLine = doc.line(cursorLine);
                        const prevLineNumber = cursorLine - insertedCount;
                        const prevLine = prevLineNumber >= 1 ? doc.line(prevLineNumber) : null;

                        // 判断回车位置：
                        // - 如果当前行（新行）为空，说明是在末尾回车
                        // - 如果上一行为空，说明是在开头回车
                        // - 否则是在中间回车
                        const currentLineContent = currentLine.text.trim();
                        const prevLineContent = prevLine ? prevLine.text.trim() : '';

                        let insertType = 'end'; // 默认末尾
                        if (currentLineContent === '' && prevLineContent !== '') {
                            insertType = 'end'; // 末尾回车：新行为空，上一行有内容
                        } else if (currentLineContent !== '' && prevLineContent === '') {
                            insertType = 'start'; // 开头回车：新行有内容，上一行为空
                        } else if (currentLineContent !== '' && prevLineContent !== '') {
                            insertType = 'middle'; // 中间回车：两行都有内容
                        }

                        const insertAfterLine = Math.max(1, cursorLine - insertedCount);
                        console.log(`[Overleaf Reader Injected] Polling detected lines inserted: ${insertedCount} after line ${insertAfterLine} (cursor at ${cursorLine}), type: ${insertType}`);
                        console.log(`[Overleaf Reader Injected] prevLine: "${prevLineContent.substring(0, 50)}", currentLine: "${currentLineContent.substring(0, 50)}"`);

                        window.postMessage({
                            type: 'OVERLEAF_LINES_INSERTED',
                            lineNumber: insertAfterLine,
                            count: insertedCount,
                            insertType: insertType, // 'start', 'middle', 'end'
                            prevLineNumber: prevLineNumber,
                            currentLineNumber: cursorLine,
                            source: window.__overleafReaderLastSource || null  // 传递来源标记
                        }, '*');
                    } else {
                        // Lines deleted
                        const deletedCount = lastPolledLineCount - newLineCount;
                        const currentLine = doc.line(cursorLine);
                        const currentLineContent = currentLine.text;

                        // 判断删除类型：
                        // - 合并操作：行首 Backspace，当前行内容变长（合并了原来下一行的内容）
                        //   特征：光标不在行首，且光标后面还有内容（cursorCol < currentLineContent.length）
                        // - 普通删除：删除空行
                        //   特征：光标在行末（cursorCol == currentLineContent.length），说明上一行是空行被删除

                        const cursorCol = cursorPos - currentLine.from; // 光标在行内的位置

                        let deleteType = 'normal';
                        // 只有当光标不在行首，且光标后面还有内容时，才是合并操作
                        // 如果光标在行末（上一行是空行），则是普通删除
                        if (cursorCol > 0 && cursorCol < currentLineContent.length) {
                            // 光标后面还有内容，说明是合并操作
                            deleteType = 'merge';
                        }

                        const deleteAtLine = cursorLine + 1; // 被删除/合并的是下一行
                        console.log(`[Overleaf Reader Injected] Polling detected lines deleted: ${deletedCount} at line ${deleteAtLine} (cursor at ${cursorLine}, col ${cursorCol}, lineLen ${currentLineContent.length}), type: ${deleteType}`);
                        window.postMessage({
                            type: 'OVERLEAF_LINES_DELETED',
                            lineNumber: deleteAtLine,
                            count: deletedCount,
                            deleteType: deleteType,
                            mergeToLine: cursorLine, // 合并到哪一行
                            source: window.__overleafReaderLastSource || null  // 传递来源标记
                        }, '*');
                    }
                }
                lastPolledLineCount = newLineCount;

                // Check for cursor position changes
                if (view.state.selection) {
                    const selection = view.state.selection.main;
                    const cursorPos = selection.head;
                    const line = doc.lineAt(cursorPos);
                    const lineNumber = line.number;

                    // Only send if line changed
                    if (lineNumber !== lastPolledCursorLine) {
                        lastPolledCursorLine = lineNumber;
                        window.postMessage({
                            type: 'OVERLEAF_CURSOR_LINE_CHANGED',
                            lineNumber: lineNumber
                        }, '*');
                    }
                }
            }
        } catch (e) {
            // Ignore errors in polling
        }
    }, 200); // Poll every 200ms for responsive tracking

    // 暴露一个函数来更新时间戳
    window.__overleafReaderMarkExternalUpdate = function() {
        lastExternalUpdateTime = Date.now();
    };

    // Listen for jump to line and update content messages
    window.addEventListener('message', async function(event) {
        if (event.data && event.data.type === 'OVERLEAF_READER_JUMP_TO_LINE') {
            const success = window.__overleafReaderJumpToLine(event.data.lineNumber);
            // Send back result
            window.postMessage({
                type: 'OVERLEAF_READER_JUMP_RESULT',
                success: success,
                lineNumber: event.data.lineNumber
            }, '*');
        } else if (event.data && event.data.type === 'OVERLEAF_READER_UPDATE_CONTENT') {
            // 设置标志，防止行变化消息被发送回去
            window.__overleafReaderExternalUpdate = true;
            const success = window.__overleafReaderUpdateContent(event.data.content, event.data.originalContent);
            // 延迟重置标志，确保 docChanged 事件已处理完
            setTimeout(() => {
                window.__overleafReaderExternalUpdate = false;
            }, 500);
            // Send back result
            window.postMessage({
                type: 'OVERLEAF_READER_UPDATE_RESULT',
                success: success
            }, '*');
        } else if (event.data && event.data.type === 'OVERLEAF_READER_DELETE_LINE') {
            // 精确删除指定行
            window.__overleafReaderExternalUpdate = true;
            window.__overleafReaderLastSource = event.data.source || null;  // 记住来源
            if (window.__overleafReaderMarkExternalUpdate) {
                window.__overleafReaderMarkExternalUpdate();
            }
            const success = window.__overleafReaderDeleteLine(event.data.lineNumber);
            setTimeout(() => {
                window.__overleafReaderExternalUpdate = false;
                window.__overleafReaderLastSource = null;
            }, 500);
            window.postMessage({
                type: 'OVERLEAF_READER_DELETE_LINE_RESULT',
                success: success,
                lineNumber: event.data.lineNumber
            }, '*');
        } else if (event.data && event.data.type === 'OVERLEAF_READER_MERGE_LINES') {
            // 合并行：将 fromLineNumber 行合并到 toLineNumber 行末尾
            window.__overleafReaderExternalUpdate = true;
            window.__overleafReaderLastSource = event.data.source || null;  // 记住来源
            if (window.__overleafReaderMarkExternalUpdate) {
                window.__overleafReaderMarkExternalUpdate();
            }
            const success = window.__overleafReaderMergeLines(event.data.toLineNumber, event.data.fromLineNumber);
            setTimeout(() => {
                window.__overleafReaderExternalUpdate = false;
                window.__overleafReaderLastSource = null;
            }, 500);
            window.postMessage({
                type: 'OVERLEAF_READER_MERGE_LINES_RESULT',
                success: success
            }, '*');
        } else if (event.data && event.data.type === 'OVERLEAF_READER_INSERT_LINE') {
            // 在指定行后插入新行
            window.__overleafReaderExternalUpdate = true;
            window.__overleafReaderLastSource = event.data.source || null;  // 记住来源
            if (window.__overleafReaderMarkExternalUpdate) {
                window.__overleafReaderMarkExternalUpdate();
            }
            const success = window.__overleafReaderInsertLineAfter(event.data.afterLineNumber);
            setTimeout(() => {
                window.__overleafReaderExternalUpdate = false;
                window.__overleafReaderLastSource = null;
            }, 500);
            window.postMessage({
                type: 'OVERLEAF_READER_INSERT_LINE_RESULT',
                success: success,
                afterLineNumber: event.data.afterLineNumber
            }, '*');
        } else if (event.data && event.data.type === 'OVERLEAF_READER_UPDATE_LINE_CONTENT') {
            // 更新指定行的内容
            window.__overleafReaderExternalUpdate = true;
            if (window.__overleafReaderMarkExternalUpdate) {
                window.__overleafReaderMarkExternalUpdate();
            }
            const success = window.__overleafReaderUpdateLineContent(event.data.lineNumber, event.data.content);
            setTimeout(() => {
                window.__overleafReaderExternalUpdate = false;
            }, 500);
            window.postMessage({
                type: 'OVERLEAF_READER_UPDATE_LINE_CONTENT_RESULT',
                success: success,
                lineNumber: event.data.lineNumber
            }, '*');
        } else if (event.data && event.data.type === 'OVERLEAF_READER_ADD_CITATION_TO_BIB') {
            try {
                const result = await window.__overleafReaderAddCitationToBib(event.data.citationKey, event.data.bibEntry);
                window.postMessage({
                    type: 'OVERLEAF_READER_CITATION_RESPONSE',
                    success: result.success,
                    error: result.error || null
                }, '*');
            } catch (error) {
                console.error('[Injected] Error adding citation to BIB:', error);
                window.postMessage({
                    type: 'OVERLEAF_READER_CITATION_RESPONSE',
                    success: false,
                    error: error.message || 'Error adding citation to BIB file'
                }, '*');
            }
        } else if (event.data && event.data.type === 'OVERLEAF_READER_INSERT_CITATION') {
            try {
                const success = window.__overleafReaderInsertCitation(event.data.citationKey);
                window.postMessage({
                    type: 'OVERLEAF_READER_CITATION_RESPONSE',
                    success: success,
                    error: success ? null : 'Failed to insert citation'
                }, '*');
            } catch (error) {
                console.error('[Injected] Error inserting citation:', error);
                window.postMessage({
                    type: 'OVERLEAF_READER_CITATION_RESPONSE',
                    success: false,
                    error: error.message || 'Error inserting citation'
                }, '*');
            }
        } else if (event.data && event.data.type === 'OVERLEAF_READER_ADD_MULTIPLE_CITATIONS') {
            try {
                const result = await window.__overleafReaderAddMultipleCitations(event.data.citationKeys, event.data.bibEntries);
                window.postMessage({
                    type: 'OVERLEAF_READER_CITATION_RESPONSE',
                    success: result.success,
                    error: result.error || null
                }, '*');
            } catch (error) {
                console.error('[Injected] Error adding multiple citations:', error);
                window.postMessage({
                    type: 'OVERLEAF_READER_CITATION_RESPONSE',
                    success: false,
                    error: error.message || 'Error adding multiple citations'
                }, '*');
            }
        } else if (event.data && event.data.type === 'OVERLEAF_READER_REPLACE_TEXT') {
            try {
                const success = window.__overleafReaderReplaceText(event.data.originalText, event.data.newText);
                window.postMessage({
                    type: 'OVERLEAF_READER_REPLACE_RESPONSE',
                    success: success,
                    error: success ? null : 'Failed to replace text'
                }, '*');
            } catch (error) {
                console.error('[Injected] Error replacing text:', error);
                window.postMessage({
                    type: 'OVERLEAF_READER_REPLACE_RESPONSE',
                    success: false,
                    error: error.message || 'Error replacing text'
                }, '*');
            }
        } else if (event.data && event.data.type === 'OVERLEAF_READER_GET_FILENAME') {
            console.log('[Injected] Received OVERLEAF_READER_GET_FILENAME request');
            try {
                const filename = window.__overleafReaderGetCurrentFile();
                console.log('[Injected] Got filename:', filename);
                console.log('[Injected] Sending OVERLEAF_READER_FILENAME_RESPONSE with:', filename || '');
                window.postMessage({
                    type: 'OVERLEAF_READER_FILENAME_RESPONSE',
                    filename: filename || ''
                }, '*');
            } catch (error) {
                console.error('[Injected] Error getting filename:', error);
                window.postMessage({
                    type: 'OVERLEAF_READER_FILENAME_RESPONSE',
                    filename: ''
                }, '*');
            }
        } else if (event.data && event.data.type === 'OVERLEAF_READER_GET_FRESH_CONTENT') {
            // 直接从编辑器获取最新内容（不使用缓存）
            console.log('[Injected] Received OVERLEAF_READER_GET_FRESH_CONTENT request');
            try {
                let content = '';
                // 使用正确的方式获取编辑器视图
                const editorView = window.overleaf?.unstable?.store?.get('editor.view');
                if (editorView && editorView.state && editorView.state.doc) {
                    content = editorView.state.doc.toString();
                }
                console.log('[Injected] Got fresh content, length:', content.length);
                window.postMessage({
                    type: 'OVERLEAF_READER_FRESH_CONTENT_RESPONSE',
                    content: content,
                    length: content.length
                }, '*');
            } catch (error) {
                console.error('[Injected] Error getting fresh content:', error);
                window.postMessage({
                    type: 'OVERLEAF_READER_FRESH_CONTENT_RESPONSE',
                    content: '',
                    length: 0,
                    error: error.message
                }, '*');
            }
        }
    });

    // Multi-file management state
    let fileStates = {
        currentFile: null,
        previousFile: null,
        editorContents: new Map()
    };

    // Get project files list
    window.__overleafReaderGetProjectFiles = function() {
        console.log('[Overleaf Reader Injected] Getting project files...');

        const files = [];

        // Try multiple selectors for file tree items
        const selectors = [
            '.file-tree-item',
            '[data-type="file"]',
            '.entity-item',
            '.entity',
            '[role="button"][data-path]',
            '.file-tree li',
            '.project-file'
        ];

        let foundItems = [];
        for (const selector of selectors) {
            const items = document.querySelectorAll(selector);
            if (items.length > 0) {
                console.log('[Overleaf Reader Injected] Found items with selector:', selector, items.length);
                foundItems = items;
                break;
            }
        }

        if (foundItems.length === 0) {
            console.log('[Overleaf Reader Injected] No file tree items found with any selector');
            return [];
        }

        foundItems.forEach(item => {
            // Try multiple ways to get the file name
            let name = '';
            let nameElement = null;

            const nameSelectors = [
                '.file-tree-item-name',
                '.entity-name',
                '.name',
                '[data-path]'
            ];

            for (const nameSelector of nameSelectors) {
                nameElement = item.querySelector(nameSelector);
                if (nameElement) {
                    name = nameElement.textContent?.trim() || nameElement.getAttribute('data-path') || '';
                    if (name) break;
                }
            }

            // If no name element found, try getting from the item itself
            if (!name) {
                name = item.textContent?.trim() || item.getAttribute('data-path') || '';

                // Clean up the name - remove extra text like "description" or "menu_book"
                if (name) {
                    // Look for file extensions and extract just the filename
                    const fileExtensions = ['.tex', '.bib', '.sty', '.cls', '.bst', '.png', '.jpg', '.pdf'];
                    for (const ext of fileExtensions) {
                        const extIndex = name.indexOf(ext);
                        if (extIndex !== -1) {
                            // Find the start of the filename (look backwards for non-alphanumeric chars)
                            let start = extIndex;
                            while (start > 0 && /[a-zA-Z0-9._-]/.test(name[start - 1])) {
                                start--;
                            }
                            name = name.substring(start, extIndex + ext.length);
                            break;
                        }
                    }
                }
            }

            // Check if it's a file (not a folder)
            const isFolder = item.classList.contains('file-tree-folder') ||
                            item.classList.contains('folder') ||
                            item.querySelector('.folder-icon') ||
                            item.querySelector('[data-type="folder"]');

            if (!isFolder && name && name.includes('.')) {
                files.push({
                    name: name,
                    element: item,
                    id: item.dataset.entityId || item.dataset.fileId || item.dataset.path,
                    isSelected: item.classList.contains('selected') || item.classList.contains('active')
                });
            }
        });

        console.log('[Overleaf Reader Injected] Found files:', files.map(f => f.name));
        return files;
    };

    // Get current active file
    window.__overleafReaderGetCurrentFile = function() {
        console.log('[Overleaf Reader Injected] === Getting current file ===');

        // First, try to get from Overleaf's exposed state (most reliable)
        try {
            console.log('[Overleaf Reader Injected] Checking window.overleaf:', window.overleaf);
            console.log('[Overleaf Reader Injected] Checking window.overleaf?.unstable:', window.overleaf?.unstable);
            console.log('[Overleaf Reader Injected] Checking window.overleaf?.unstable?.store:', window.overleaf?.unstable?.store);

            if (window.overleaf?.unstable?.store) {
                const store = window.overleaf.unstable.store;
                console.log('[Overleaf Reader Injected] Full store contents:', store);
                console.log('[Overleaf Reader Injected] All store keys:', Object.keys(store));

                // The actual data is in store.items (which is a Map)
                if (store.items) {
                    console.log('[Overleaf Reader Injected] Store.items exists:', store.items);
                    console.log('[Overleaf Reader Injected] Store.items is Map:', store.items instanceof Map);

                    // store.items is a Map, use .get() method
                    const openDocNameObj = store.items.get('editor.open_doc_name');
                    console.log('[Overleaf Reader Injected] editor.open_doc_name object:', openDocNameObj);

                    // The value is stored in a wrapper object with 'value' property
                    const openDocName = openDocNameObj?.value;
                    console.log('[Overleaf Reader Injected] editor.open_doc_name value:', openDocName);

                    if (openDocName) {
                        console.log('[Overleaf Reader Injected] ✓ Got filename from overleaf.unstable.store.items:', openDocName);
                        return openDocName;
                    } else {
                        console.log('[Overleaf Reader Injected] ✗ editor.open_doc_name is empty or null');
                    }
                } else {
                    console.log('[Overleaf Reader Injected] ✗ store.items does not exist');
                }
            } else {
                console.log('[Overleaf Reader Injected] ✗ window.overleaf.unstable.store does not exist');
            }
        } catch (e) {
            console.log('[Overleaf Reader Injected] ✗ Error accessing overleaf.unstable.store:', e);
        }

        // Fallback: Try multiple selectors for selected/active file
        const selectors = [
            '.file-tree-item.selected',
            '.entity.selected',
            '.entity.active',
            '[data-type="file"].selected',
            '[data-type="file"].active'
        ];

        let selectedItem = null;
        for (const selector of selectors) {
            selectedItem = document.querySelector(selector);
            if (selectedItem) break;
        }

        if (selectedItem) {
            // Use the same logic as in getProjectFiles to extract name
            const nameSelectors = [
                '.file-tree-item-name',
                '.entity-name',
                '.name',
                '[data-path]'
            ];

            for (const nameSelector of nameSelectors) {
                const nameElement = selectedItem.querySelector(nameSelector);
                if (nameElement) {
                    let name = nameElement.textContent?.trim() || nameElement.getAttribute('data-path') || '';
                    if (name) {
                        // Apply same name cleaning logic
                        const fileExtensions = ['.tex', '.bib', '.sty', '.cls', '.bst', '.png', '.jpg', '.pdf'];
                        for (const ext of fileExtensions) {
                            const extIndex = name.indexOf(ext);
                            if (extIndex !== -1) {
                                let start = extIndex;
                                while (start > 0 && /[a-zA-Z0-9._-]/.test(name[start - 1])) {
                                    start--;
                                }
                                name = name.substring(start, extIndex + ext.length);
                                break;
                            }
                        }
                        return name;
                    }
                }
            }

            // Fallback to item text content
            let name = selectedItem.textContent?.trim() || '';
            if (name) {
                const fileExtensions = ['.tex', '.bib', '.sty', '.cls', '.bst', '.png', '.jpg', '.pdf'];
                for (const ext of fileExtensions) {
                    const extIndex = name.indexOf(ext);
                    if (extIndex !== -1) {
                        let start = extIndex;
                        while (start > 0 && /[a-zA-Z0-9._-]/.test(name[start - 1])) {
                            start--;
                        }
                        name = name.substring(start, extIndex + ext.length);
                        return name;
                    }
                }
            }
        }
        return null;
    };

    // Switch to a specific file
    window.__overleafReaderSwitchToFile = function(fileName) {
        console.log('[Overleaf Reader Injected] Switching to file:', fileName);

        const files = window.__overleafReaderGetProjectFiles();
        console.log('[Overleaf Reader Injected] Available files for switching:', files.map(f => f.name));

        // Try exact match first, then partial match
        let targetFile = files.find(f => f.name === fileName);
        if (!targetFile) {
            targetFile = files.find(f => f.name.includes(fileName));
        }

        console.log('[Overleaf Reader Injected] Target file found:', targetFile?.name);

        if (targetFile && targetFile.element) {
            // Save current state before switching
            const currentFile = window.__overleafReaderGetCurrentFile();
            if (currentFile) {
                const currentContent = window.__overleafReaderGetContent();
                fileStates.editorContents.set(currentFile, currentContent);
                fileStates.previousFile = currentFile;
            }

            // Click the file to switch
            console.log('[Overleaf Reader Injected] Clicking file element...');
            targetFile.element.click();
            fileStates.currentFile = targetFile.name;

            console.log('[Overleaf Reader Injected] Switched to file:', targetFile.name);
            return true;
        }

        console.log('[Overleaf Reader Injected] File not found or no clickable element:', fileName);
        if (!targetFile) {
            console.log('[Overleaf Reader Injected] File not found in file list');
        } else {
            console.log('[Overleaf Reader Injected] File found but no clickable element');
        }
        return false;
    };

    // Wait for file to load
    window.__overleafReaderWaitForFileLoad = function(timeout = 3000) {
        return new Promise((resolve, reject) => {
            const startTime = Date.now();

            const checkLoaded = () => {
                try {
                    const view = window.overleaf?.unstable?.store?.get('editor.view');
                    if (view && view.state && view.state.doc) {
                        console.log('[Overleaf Reader Injected] File loaded successfully');
                        resolve();
                        return;
                    }
                } catch (e) {
                    console.log('[Overleaf Reader Injected] Checking file load...', e.message);
                }

                if (Date.now() - startTime > timeout) {
                    reject(new Error('File load timeout'));
                    return;
                }

                setTimeout(checkLoaded, 200);
            };

            checkLoaded();
        });
    };

    // Replace selected text with new text using incremental diff-based update
    window.__overleafReaderReplaceText = function(originalText, newText) {
        console.log('[Overleaf Reader Injected] Replacing text with incremental update');
        console.log('[Overleaf Reader Injected] Original text length:', originalText.length);
        console.log('[Overleaf Reader Injected] New text length:', newText.length);

        try {
            // Method 1: Try using Overleaf's editor API with incremental changes
            const editorView = window.overleaf?.unstable?.store?.get('editor.view');
            if (editorView) {
                const doc = editorView.state.doc;
                const docText = doc.toString();

                // Find the position of the original text
                const pos = docText.indexOf(originalText);
                if (pos !== -1) {
                    // Get the full text with the replacement
                    const beforeText = docText.substring(0, pos);
                    const afterText = docText.substring(pos + originalText.length);
                    const fullNewText = beforeText + newText + afterText;

                    // Calculate incremental changes between current doc and new doc
                    const changes = calculateDiff(docText, fullNewText);

                    if (changes.length === 0) {
                        console.log('[Overleaf Reader Injected] No changes needed - text already matches');
                        return true;
                    }

                    // Apply the incremental changes
                    editorView.dispatch({ changes: changes });

                    console.log('[Overleaf Reader Injected] Text replaced successfully using incremental update');
                    console.log('[Overleaf Reader Injected] Applied', changes.length, 'change operations');
                    return true;
                } else {
                    console.log('[Overleaf Reader Injected] Could not find original text in document');
                    // Try fuzzy search for similar text
                    if (originalText.length > 20) {
                        const searchText = originalText.substring(0, 20);
                        const fuzzyPos = docText.indexOf(searchText);
                        if (fuzzyPos !== -1) {
                            console.log('[Overleaf Reader Injected] Found partial match at position:', fuzzyPos);
                        }
                    }
                    return false;
                }
            }

            // Method 2: Try with stored editor view
            if (window.__overleafEditorView) {
                const view = window.__overleafEditorView;
                const doc = view.state.doc;
                const docText = doc.toString();

                const pos = docText.indexOf(originalText);
                if (pos !== -1) {
                    const beforeText = docText.substring(0, pos);
                    const afterText = docText.substring(pos + originalText.length);
                    const fullNewText = beforeText + newText + afterText;

                    const changes = calculateDiff(docText, fullNewText);

                    if (changes.length > 0) {
                        view.dispatch({ changes: changes });
                        console.log('[Overleaf Reader Injected] Text replaced successfully using stored view with incremental update');
                        return true;
                    }
                    return true;
                }
            }

            console.log('[Overleaf Reader Injected] No suitable editor view found for replacement');
            return false;
        } catch (error) {
            console.error('[Overleaf Reader Injected] Error replacing text:', error);
            return false;
        }
    };

    // Insert citation at cursor position
    window.__overleafReaderInsertCitation = function(citationKey) {
        console.log('[Overleaf Reader Injected] Inserting citation:', citationKey);

        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view) return false;

            const selection = view.state.selection.main;
            // If there's a selection, insert at the end (to), otherwise at cursor (head)
            const insertPos = selection.from !== selection.to ? selection.to : selection.head;
            const citationText = `\\cite{${citationKey}}`;

            console.log('[Overleaf Reader Injected] Inserting citation at position:', insertPos);
            console.log('[Overleaf Reader Injected] Selection range:', selection.from, '-', selection.to);

            view.dispatch({
                changes: {
                    from: insertPos,
                    to: insertPos,
                    insert: citationText
                },
                selection: { anchor: insertPos + citationText.length }
            });

            console.log('[Overleaf Reader Injected] Citation inserted successfully');
            return true;
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error inserting citation:', e);
            return false;
        }
    };

    // Add multiple citations to BIB file
    window.__overleafReaderAddMultipleCitations = async function(citationKeys, bibEntries) {
        console.log('[Overleaf Reader Injected] Adding multiple citations workflow for:', citationKeys);

        try {
            // 1. First, insert all citations in current document as \cite{key1,key2,key3}
            console.log('[Overleaf Reader Injected] Step 1: Inserting \\cite{} with multiple keys in current document...');
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view) {
                throw new Error('Could not access editor view');
            }

            const selection = view.state.selection.main;
            const insertPos = selection.from !== selection.to ? selection.to : selection.head;
            const citationText = `\\cite{${citationKeys.join(',')}}`;

            view.dispatch({
                changes: {
                    from: insertPos,
                    to: insertPos,
                    insert: citationText
                },
                selection: { anchor: insertPos + citationText.length }
            });

            console.log('[Overleaf Reader Injected] Multiple citations inserted successfully');

            // 2. Get current file for later reference
            let originalFile = window.__overleafReaderGetCurrentFile();
            console.log('[Overleaf Reader Injected] Current file:', originalFile);

            if (!originalFile) {
                const files = window.__overleafReaderGetProjectFiles();
                const activeFile = files.find(f => f.isSelected);
                if (activeFile) {
                    originalFile = activeFile.name;
                }
            }

            // 3. Find BIB file
            console.log('[Overleaf Reader Injected] Step 2: Finding BIB file...');
            const files = window.__overleafReaderGetProjectFiles();
            let bibFile = files.find(f => f.name.toLowerCase().endsWith('.bib'));

            if (!bibFile) {
                bibFile = files.find(f => f.name.toLowerCase().includes('bib'));
                if (!bibFile) {
                    throw new Error('No BIB file found in project');
                }
            }

            // 4. Switch to BIB file
            console.log('[Overleaf Reader Injected] Step 3: Switching to BIB file...');
            const switched = window.__overleafReaderSwitchToFile(bibFile.name);
            if (!switched) {
                throw new Error('Failed to switch to BIB file');
            }

            // 5. Wait for BIB file to load
            await window.__overleafReaderWaitForFileLoad();
            await new Promise(resolve => setTimeout(resolve, 1000));

            // 6. Get BIB content and add all new entries
            console.log('[Overleaf Reader Injected] Step 4: Adding entries to BIB file...');
            const bibContent = window.__overleafReaderGetContent();
            const allNewEntries = bibEntries.join('\n\n');
            const updatedBibContent = bibContent + '\n\n' + allNewEntries;

            console.log('[Overleaf Reader Injected] Updating BIB file with', bibEntries.length, 'new entries...');

            // 7. Update BIB file
            const updateSuccess = window.__overleafReaderUpdateContent(updatedBibContent, bibContent);
            if (!updateSuccess) {
                throw new Error('Failed to update BIB file');
            }

            console.log('[Overleaf Reader Injected] BIB file updated successfully');

            // 8. Switch back to original file
            console.log('[Overleaf Reader Injected] Step 5: Switching back to original file...');
            if (originalFile) {
                const switchedBack = window.__overleafReaderSwitchToFile(originalFile);
                if (switchedBack) {
                    await window.__overleafReaderWaitForFileLoad();
                }
            }

            console.log('[Overleaf Reader Injected] Multiple citations added successfully');
            return { success: true, message: `${citationKeys.length} citations added to ${bibFile.name}` };

        } catch (error) {
            console.error('[Overleaf Reader Injected] Error adding multiple citations:', error);
            return { success: false, error: error.message };
        }
    };

    // Add citation to BIB file
    window.__overleafReaderAddCitationToBib = async function(citationKey, bibEntry) {
        console.log('[Overleaf Reader Injected] Adding citation workflow for:', citationKey);

        try {
            // 1. First, insert citation in current document
            console.log('[Overleaf Reader Injected] Step 1: Inserting \\cite{} in current document...');
            const citationInserted = window.__overleafReaderInsertCitation(citationKey);

            if (!citationInserted) {
                console.log('[Overleaf Reader Injected] Warning: Failed to insert citation, but continuing...');
            } else {
                console.log('[Overleaf Reader Injected] Citation inserted successfully');
            }

            // 2. Get current file for later reference
            let originalFile = window.__overleafReaderGetCurrentFile();
            console.log('[Overleaf Reader Injected] Current file:', originalFile);

            // If we can't get the current file, try to get it from the files list
            if (!originalFile) {
                const files = window.__overleafReaderGetProjectFiles();
                const activeFile = files.find(f => f.isSelected);
                console.log('[Overleaf Reader Injected] Fallback - found active file:', activeFile?.name);

                if (activeFile) {
                    originalFile = activeFile.name;
                }
            }

            // 3. Find BIB file
            console.log('[Overleaf Reader Injected] Step 2: Finding BIB file...');
            const files = window.__overleafReaderGetProjectFiles();
            console.log('[Overleaf Reader Injected] All project files:', files.map(f => f.name));

            let bibFile = files.find(f => f.name.toLowerCase().endsWith('.bib'));
            console.log('[Overleaf Reader Injected] Found BIB file:', bibFile);

            if (!bibFile) {
                // Try different extensions or patterns
                bibFile = files.find(f => f.name.toLowerCase().includes('bib'));
                console.log('[Overleaf Reader Injected] Found file with "bib" in name:', bibFile);

                if (!bibFile) {
                    const fileNames = files.map(f => f.name).join(', ');
                    throw new Error(`No BIB file found in project. Available files: ${fileNames}. Please create a .bib file or rename an existing file to end with .bib`);
                }
            }

            // 4. Switch to BIB file
            console.log('[Overleaf Reader Injected] Step 3: Switching to BIB file...');
            const switched = window.__overleafReaderSwitchToFile(bibFile.name);
            if (!switched) {
                throw new Error('Failed to switch to BIB file');
            }

            console.log('[Overleaf Reader Injected] Switched to BIB file:', bibFile.name);

            // 5. Wait for BIB file to load
            await window.__overleafReaderWaitForFileLoad();

            // 6. Get BIB content and add new entry
            console.log('[Overleaf Reader Injected] Step 4: Adding entry to BIB file...');

            // Wait a bit more to ensure content is loaded
            await new Promise(resolve => setTimeout(resolve, 1000));

            const bibContent = window.__overleafReaderGetContent();
            console.log('[Overleaf Reader Injected] BIB content length:', bibContent.length);
            console.log('[Overleaf Reader Injected] BIB content preview:', bibContent.substring(0, 200));

            // Check if the content looks like a BIB file
            const isBibContent = bibContent.includes('@') || bibContent.trim() === '';
            console.log('[Overleaf Reader Injected] Content appears to be BIB file:', isBibContent);

            if (!isBibContent && bibContent.length > 100) {
                console.log('[Overleaf Reader Injected] Content doesn\'t look like BIB file, waiting longer...');
                await new Promise(resolve => setTimeout(resolve, 2000));
                const newBibContent = window.__overleafReaderGetContent();
                console.log('[Overleaf Reader Injected] New BIB content length:', newBibContent.length);
            }

            const finalBibContent = window.__overleafReaderGetContent();
            const updatedBibContent = finalBibContent + '\n\n' + bibEntry;

            console.log('[Overleaf Reader Injected] Updating BIB file with new entry...');
            console.log('[Overleaf Reader Injected] Adding entry:', bibEntry);

            // 6. Update BIB file
            const updateSuccess = window.__overleafReaderUpdateContent(updatedBibContent, finalBibContent);

            if (!updateSuccess) {
                throw new Error('Failed to update BIB file');
            }

            console.log('[Overleaf Reader Injected] BIB file updated successfully');

            // 7. Switch back to original file
            console.log('[Overleaf Reader Injected] Step 5: Switching back to original file...');

            if (originalFile) {
                console.log('[Overleaf Reader Injected] Switching back to:', originalFile);
                const switchedBack = window.__overleafReaderSwitchToFile(originalFile);
                if (switchedBack) {
                    console.log('[Overleaf Reader Injected] Successfully switched back to original file');
                    await window.__overleafReaderWaitForFileLoad();
                } else {
                    console.log('[Overleaf Reader Injected] Failed to switch back to original file');
                }
            } else {
                console.log('[Overleaf Reader Injected] No original file detected, trying to find TEX file...');
                // Try to find any .tex file and switch to it
                const allFiles = window.__overleafReaderGetProjectFiles();
                const texFiles = allFiles.filter(f => f.name.toLowerCase().endsWith('.tex'));
                console.log('[Overleaf Reader Injected] Found TEX files:', texFiles.map(f => f.name));

                if (texFiles.length > 0) {
                    // Prefer main.tex or the first one
                    const mainFile = texFiles.find(f => f.name.toLowerCase().includes('main')) || texFiles[0];
                    console.log('[Overleaf Reader Injected] Switching to TEX file:', mainFile.name);

                    const switched = window.__overleafReaderSwitchToFile(mainFile.name);
                    if (switched) {
                        console.log('[Overleaf Reader Injected] Successfully switched to TEX file');
                        await window.__overleafReaderWaitForFileLoad();
                    } else {
                        console.log('[Overleaf Reader Injected] Failed to switch to TEX file');
                    }
                } else {
                    console.log('[Overleaf Reader Injected] No TEX files found, staying in BIB file');
                }
            }

            console.log('[Overleaf Reader Injected] Citation added successfully');
            return { success: true, message: `Citation ${citationKey} added to ${bibFile.name}` };

        } catch (error) {
            console.error('[Overleaf Reader Injected] Error adding citation:', error);

            // Try to switch back to original file on error
            const originalFile = fileStates.previousFile;
            if (originalFile) {
                window.__overleafReaderSwitchToFile(originalFile);
            }

            return { success: false, error: error.message };
        }
    };

    console.log('[Overleaf Reader Injected] Setup complete with multi-file support');

    // =================== Diff Preview Popup Functions ===================

    // LCS-based diff algorithm for accurate word-level comparison
    function computeWordDiff(original, modified) {
        const originalWords = original.split(/(\s+)/);
        const modifiedWords = modified.split(/(\s+)/);

        const m = originalWords.length;
        const n = modifiedWords.length;

        // Build LCS table
        const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));

        for (let i = 1; i <= m; i++) {
            for (let j = 1; j <= n; j++) {
                if (originalWords[i - 1] === modifiedWords[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }

        // Backtrack to find diff
        const result = [];
        let i = m, j = n;

        while (i > 0 || j > 0) {
            if (i > 0 && j > 0 && originalWords[i - 1] === modifiedWords[j - 1]) {
                result.unshift({ type: 'equal', value: originalWords[i - 1] });
                i--;
                j--;
            } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
                result.unshift({ type: 'add', value: modifiedWords[j - 1] });
                j--;
            } else if (i > 0) {
                result.unshift({ type: 'delete', value: originalWords[i - 1] });
                i--;
            }
        }

        return result;
    }

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

    function renderWordDiff(diff) {
        return diff.map(part => {
            if (part.type === 'add') {
                return `<span class="overleaf-diff-add">${escapeHtmlForDiff(part.value)}</span>`;
            } else if (part.type === 'delete') {
                return `<span class="overleaf-diff-delete">${escapeHtmlForDiff(part.value)}</span>`;
            } else {
                return escapeHtmlForDiff(part.value);
            }
        }).join('');
    }

    // Inject CSS styles for diff popup
    function injectDiffPopupStyles() {
        if (document.getElementById('overleaf-diff-popup-styles')) return;

        const style = document.createElement('style');
        style.id = 'overleaf-diff-popup-styles';
        style.textContent = `
            .overleaf-diff-popup {
                position: absolute;
                z-index: 100000;
                background: white;
                border-radius: 12px;
                box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(0, 0, 0, 0.08);
                max-width: 600px;
                min-width: 400px;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                animation: overleafDiffPopupFadeIn 0.2s ease-out;
            }
            @keyframes overleafDiffPopupFadeIn {
                from { opacity: 0; transform: translateY(-8px); }
                to { opacity: 1; transform: translateY(0); }
            }
            .overleaf-diff-popup-header {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 12px 16px;
                border-bottom: 1px solid #e5e7eb;
                background: #f9fafb;
                border-radius: 12px 12px 0 0;
            }
            .overleaf-diff-popup-title {
                font-size: 14px;
                font-weight: 600;
                color: #111827;
            }
            .overleaf-diff-popup-close {
                width: 28px;
                height: 28px;
                border: none;
                background: transparent;
                color: #6b7280;
                font-size: 20px;
                cursor: pointer;
                border-radius: 6px;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: all 0.15s;
            }
            .overleaf-diff-popup-close:hover {
                background: #e5e7eb;
                color: #111827;
            }
            .overleaf-diff-popup-content {
                padding: 16px;
                max-height: 300px;
                overflow-y: auto;
            }
            .overleaf-diff-popup-label {
                font-size: 12px;
                font-weight: 500;
                color: #6b7280;
                margin-bottom: 8px;
            }
            .overleaf-diff-popup-text {
                font-size: 14px;
                line-height: 1.7;
                color: #374151;
                background: #f9fafb;
                padding: 12px 14px;
                border-radius: 8px;
                border: 1px solid #e5e7eb;
                word-wrap: break-word;
                white-space: pre-wrap;
                font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
            }
            .overleaf-diff-popup-footer {
                display: flex;
                gap: 10px;
                padding: 12px 16px;
                border-top: 1px solid #e5e7eb;
                background: #f9fafb;
                border-radius: 0 0 12px 12px;
            }
            .overleaf-diff-popup-cancel {
                flex: 1;
                padding: 10px 16px;
                border: 1px solid #d1d5db;
                background: white;
                color: #374151;
                font-size: 14px;
                font-weight: 500;
                border-radius: 8px;
                cursor: pointer;
                transition: all 0.15s;
            }
            .overleaf-diff-popup-cancel:hover {
                background: #f3f4f6;
                border-color: #9ca3af;
            }
            .overleaf-diff-popup-confirm {
                flex: 1;
                padding: 10px 16px;
                border: none;
                background: linear-gradient(135deg, #10b981 0%, #059669 100%);
                color: white;
                font-size: 14px;
                font-weight: 500;
                border-radius: 8px;
                cursor: pointer;
                transition: all 0.15s;
            }
            .overleaf-diff-popup-confirm:hover {
                background: linear-gradient(135deg, #059669 0%, #047857 100%);
                box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
            }
            .overleaf-diff-popup-confirm:disabled {
                background: #9ca3af;
                cursor: not-allowed;
                box-shadow: none;
            }
            .overleaf-diff-add {
                background-color: #d1fae5;
                color: #065f46;
                padding: 1px 2px;
                border-radius: 2px;
            }
            .overleaf-diff-delete {
                background-color: #fee2e2;
                color: #991b1b;
                text-decoration: line-through;
                padding: 1px 2px;
                border-radius: 2px;
            }
            .overleaf-diff-popup-overlay {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                z-index: 99999;
            }
        `;
        document.head.appendChild(style);
    }

    // Show diff preview popup at the specified line
    window.__overleafReaderShowDiffPopup = function(lineNumber, originalText, updatedText) {
        console.log('[Overleaf Reader Injected] Showing diff popup for line:', lineNumber);

        // Inject styles if not already present
        injectDiffPopupStyles();

        // Remove any existing popup
        const existingPopup = document.getElementById('overleaf-diff-popup');
        const existingOverlay = document.getElementById('overleaf-diff-popup-overlay');
        if (existingPopup) existingPopup.remove();
        if (existingOverlay) existingOverlay.remove();

        // Get the editor view to find line position
        const view = window.overleaf?.unstable?.store?.get('editor.view');
        if (!view || !view.state || !view.state.doc) {
            console.error('[Overleaf Reader Injected] Cannot get editor view for popup');
            return { success: false, error: 'Cannot access editor' };
        }

        const doc = view.state.doc;
        if (lineNumber < 1 || lineNumber > doc.lines) {
            console.error('[Overleaf Reader Injected] Line number out of range:', lineNumber);
            return { success: false, error: 'Line number out of range' };
        }

        // Get line position in editor
        const line = doc.line(lineNumber);
        const coords = view.coordsAtPos(line.from);

        if (!coords) {
            console.error('[Overleaf Reader Injected] Cannot get coordinates for line');
            return { success: false, error: 'Cannot get line coordinates' };
        }

        // Scroll to the line first
        view.dispatch({
            selection: { anchor: line.from, head: line.from },
            scrollIntoView: true
        });

        // Wait a bit for scroll to complete, then show popup
        setTimeout(() => {
            // Get fresh coordinates after scroll
            const freshCoords = view.coordsAtPos(line.from);
            if (!freshCoords) return;

            // Compute diff
            const diff = computeWordDiff(originalText, updatedText);
            const diffHtml = renderWordDiff(diff);

            // Create overlay for click-outside detection
            const overlay = document.createElement('div');
            overlay.id = 'overleaf-diff-popup-overlay';
            overlay.className = 'overleaf-diff-popup-overlay';

            // Create popup
            const popup = document.createElement('div');
            popup.id = 'overleaf-diff-popup';
            popup.className = 'overleaf-diff-popup';
            popup.innerHTML = `
                <div class="overleaf-diff-popup-header">
                    <span class="overleaf-diff-popup-title">第 ${lineNumber} 行更新预览</span>
                    <button class="overleaf-diff-popup-close" title="关闭">×</button>
                </div>
                <div class="overleaf-diff-popup-content">
                    <div class="overleaf-diff-popup-label">变更内容：</div>
                    <div class="overleaf-diff-popup-text">${diffHtml}</div>
                </div>
                <div class="overleaf-diff-popup-footer">
                    <button class="overleaf-diff-popup-cancel">取消</button>
                    <button class="overleaf-diff-popup-confirm">确认更新</button>
                </div>
            `;

            // Add to document
            document.body.appendChild(overlay);
            document.body.appendChild(popup);

            // Position popup near the line
            const popupRect = popup.getBoundingClientRect();
            let top = freshCoords.bottom + 10;
            let left = freshCoords.left;

            // Ensure popup stays within viewport
            if (top + popupRect.height > window.innerHeight - 20) {
                top = freshCoords.top - popupRect.height - 10;
            }
            if (left + popupRect.width > window.innerWidth - 20) {
                left = window.innerWidth - popupRect.width - 20;
            }
            if (left < 20) left = 20;
            if (top < 20) top = 20;

            popup.style.top = `${top}px`;
            popup.style.left = `${left}px`;

            // Bind events
            const closeBtn = popup.querySelector('.overleaf-diff-popup-close');
            const cancelBtn = popup.querySelector('.overleaf-diff-popup-cancel');
            const confirmBtn = popup.querySelector('.overleaf-diff-popup-confirm');

            const cleanup = () => {
                popup.remove();
                overlay.remove();
            };

            closeBtn.addEventListener('click', () => {
                cleanup();
                window.postMessage({ type: 'OVERLEAF_DIFF_POPUP_RESULT', confirmed: false }, '*');
            });

            cancelBtn.addEventListener('click', () => {
                cleanup();
                window.postMessage({ type: 'OVERLEAF_DIFF_POPUP_RESULT', confirmed: false }, '*');
            });

            overlay.addEventListener('click', () => {
                cleanup();
                window.postMessage({ type: 'OVERLEAF_DIFF_POPUP_RESULT', confirmed: false }, '*');
            });

            confirmBtn.addEventListener('click', () => {
                confirmBtn.disabled = true;
                confirmBtn.textContent = '更新中...';

                // Apply the update
                try {
                    const success = window.__overleafReaderUpdateLineContent(lineNumber, updatedText);
                    cleanup();
                    window.postMessage({
                        type: 'OVERLEAF_DIFF_POPUP_RESULT',
                        confirmed: true,
                        success: success
                    }, '*');
                } catch (error) {
                    cleanup();
                    window.postMessage({
                        type: 'OVERLEAF_DIFF_POPUP_RESULT',
                        confirmed: true,
                        success: false,
                        error: error.message
                    }, '*');
                }
            });
        }, 150);

        return { success: true };
    };

    // Hide diff popup
    window.__overleafReaderHideDiffPopup = function() {
        const popup = document.getElementById('overleaf-diff-popup');
        const overlay = document.getElementById('overleaf-diff-popup-overlay');
        if (popup) popup.remove();
        if (overlay) overlay.remove();
    };

    // Listen for diff popup messages
    window.addEventListener('message', function(event) {
        if (event.data && event.data.type === 'OVERLEAF_READER_SHOW_DIFF_POPUP') {
            const result = window.__overleafReaderShowDiffPopup(
                event.data.lineNumber,
                event.data.originalText,
                event.data.updatedText
            );
            window.postMessage({
                type: 'OVERLEAF_READER_SHOW_DIFF_POPUP_RESULT',
                ...result
            }, '*');
        }
    });

    // =================== 编辑弹窗功能（氛围写作） ===================

    // 注入编辑弹窗样式
    function injectEditPopupStyles() {
        if (document.getElementById('overleaf-edit-popup-styles')) return;

        const style = document.createElement('style');
        style.id = 'overleaf-edit-popup-styles';
        style.textContent = `
            .overleaf-edit-popup-overlay {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(0, 0, 0, 0.3);
                z-index: 10000;
            }

            .overleaf-edit-popup {
                position: fixed;
                background: white;
                border-radius: 8px;
                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
                z-index: 10001;
                min-width: 450px;
                max-width: 700px;
                max-height: 500px;
                display: flex;
                flex-direction: column;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            }

            .overleaf-edit-popup-header {
                display: flex;
                align-items: center;
                padding: 12px 16px;
                border-bottom: 1px solid #e5e7eb;
                gap: 10px;
            }

            .edit-type-badge {
                padding: 3px 10px;
                border-radius: 4px;
                font-size: 12px;
                font-weight: 600;
            }

            .edit-type-badge.delete { background: #fee2e2; color: #dc2626; }
            .edit-type-badge.insert { background: #dcfce7; color: #16a34a; }
            .edit-type-badge.modify { background: #fef3c7; color: #d97706; }

            .edit-file-name {
                padding: 3px 8px;
                background: #e0e7ff;
                color: #3730a3;
                border-radius: 4px;
                font-size: 12px;
                font-family: 'SF Mono', Monaco, 'Consolas', monospace;
            }

            .edit-popup-title {
                flex: 1;
                font-size: 14px;
                font-weight: 500;
                color: #374151;
            }

            .edit-popup-close {
                background: none;
                border: none;
                font-size: 20px;
                color: #9ca3af;
                cursor: pointer;
                padding: 0 4px;
            }

            .edit-popup-close:hover { color: #4b5563; }

            .overleaf-edit-popup-content {
                padding: 16px;
                overflow-y: auto;
                flex: 1;
                max-height: 350px;
            }

            .edit-preview-label {
                font-size: 12px;
                color: #6b7280;
                margin-bottom: 8px;
            }

            .edit-line {
                display: flex;
                padding: 6px 10px;
                font-family: 'SF Mono', Monaco, 'Consolas', monospace;
                font-size: 13px;
                border-radius: 4px;
                margin-bottom: 4px;
                line-height: 1.5;
            }

            .edit-line.delete { background: #fee2e2; }
            .edit-line.insert { background: #dcfce7; }
            .edit-line.modify { background: #fef9c3; }

            .edit-line .line-num {
                color: #6b7280;
                min-width: 45px;
                margin-right: 12px;
                user-select: none;
                flex-shrink: 0;
            }

            .edit-line .line-text,
            .edit-line .line-diff {
                flex: 1;
                white-space: pre-wrap;
                word-break: break-all;
            }

            .edit-line .line-diff del,
            .edit-line .line-diff .overleaf-diff-delete {
                background: #fecaca;
                color: #991b1b;
                text-decoration: line-through;
                padding: 1px 2px;
                border-radius: 2px;
            }

            .edit-line .line-diff ins,
            .edit-line .line-diff .overleaf-diff-add {
                background: #bbf7d0;
                color: #166534;
                text-decoration: none;
                padding: 1px 2px;
                border-radius: 2px;
            }

            .overleaf-edit-popup-footer {
                display: flex;
                justify-content: flex-end;
                gap: 10px;
                padding: 12px 16px;
                border-top: 1px solid #e5e7eb;
            }

            .edit-popup-cancel {
                padding: 8px 18px;
                background: #f3f4f6;
                border: 1px solid #d1d5db;
                border-radius: 6px;
                cursor: pointer;
                font-size: 14px;
                color: #374151;
            }

            .edit-popup-cancel:hover { background: #e5e7eb; }

            .edit-popup-confirm {
                padding: 8px 18px;
                background: #3b82f6;
                color: white;
                border: none;
                border-radius: 6px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 500;
            }

            .edit-popup-confirm:hover { background: #2563eb; }
            .edit-popup-confirm:disabled { background: #93c5fd; cursor: not-allowed; }
        `;
        document.head.appendChild(style);
    }

    // 转义HTML
    function escapeHtmlForEdit(text) {
        if (!text) return '';
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    // 生成编辑预览HTML
    function generateEditPreviewHtml(edit, view) {
        const doc = view.state.doc;
        let html = '';

        switch (edit.type) {
            case 'delete':
                html = '<div class="edit-preview-label">将删除以下内容：</div>';
                for (let i = edit.startLine; i <= edit.endLine; i++) {
                    if (i >= 1 && i <= doc.lines) {
                        const lineText = doc.line(i).text;
                        html += `<div class="edit-line delete"><span class="line-num">${i}</span><span class="line-text">${escapeHtmlForEdit(lineText)}</span></div>`;
                    }
                }
                break;

            case 'insert':
                html = `<div class="edit-preview-label">将在第 ${edit.afterLine} 行后插入：</div>`;
                const insertLines = Object.entries(edit.lines || {}).sort((a, b) => parseInt(a[0]) - parseInt(b[0]));
                for (const [lineNum, content] of insertLines) {
                    html += `<div class="edit-line insert"><span class="line-num">${lineNum}</span><span class="line-text">${escapeHtmlForEdit(content)}</span></div>`;
                }
                break;

            case 'modify':
                html = '<div class="edit-preview-label">将修改以下行：</div>';
                const modifyLines = Object.entries(edit.lines || {}).sort((a, b) => parseInt(a[0]) - parseInt(b[0]));
                for (const [lineNum, newContent] of modifyLines) {
                    const lineNumber = parseInt(lineNum);
                    if (lineNumber >= 1 && lineNumber <= doc.lines) {
                        const oldContent = doc.line(lineNumber).text;
                        // 使用简单的diff显示
                        const diffHtml = computeWordDiff(oldContent, newContent);
                        const renderedDiff = renderWordDiff(diffHtml);
                        html += `<div class="edit-line modify"><span class="line-num">${lineNum}</span><span class="line-diff">${renderedDiff}</span></div>`;
                    }
                }
                break;
        }

        return html;
    }

    // 获取编辑目标行（用于滚动定位）
    function getEditTargetLine(edit) {
        switch (edit.type) {
            case 'delete':
                return edit.startLine;
            case 'insert':
                return edit.afterLine || 1;
            case 'modify':
                const lineNums = Object.keys(edit.lines || {}).map(n => parseInt(n)).sort((a, b) => a - b);
                return lineNums.length > 0 ? lineNums[0] : 1;
            default:
                return 1;
        }
    }

    // 应用删除操作
    function applyDeleteEdit(view, startLine, endLine) {
        const doc = view.state.doc;
        if (startLine < 1 || endLine > doc.lines || startLine > endLine) {
            console.error('[Injected] Invalid line range for delete:', startLine, endLine);
            return false;
        }

        const from = doc.line(startLine).from;
        // 如果删除到最后一行，不包含末尾换行符
        const to = endLine === doc.lines ? doc.line(endLine).to : doc.line(endLine).to + 1;

        view.dispatch({
            changes: { from, to, insert: '' }
        });
        console.log('[Injected] Deleted lines', startLine, 'to', endLine);
        return true;
    }

    // 应用插入操作
    function applyInsertEdit(view, afterLine, lines) {
        const doc = view.state.doc;
        const sortedLines = Object.entries(lines)
            .sort((a, b) => parseInt(a[0]) - parseInt(b[0]))
            .map(([_, content]) => content);

        if (sortedLines.length === 0) {
            console.error('[Injected] No lines to insert');
            return false;
        }

        let insertPos;
        let insertText;

        if (afterLine === 0) {
            // 在文档开头插入
            insertPos = 0;
            insertText = sortedLines.join('\n') + '\n';
        } else if (afterLine >= doc.lines) {
            // 在文档末尾插入
            insertPos = doc.line(doc.lines).to;
            insertText = '\n' + sortedLines.join('\n');
        } else {
            // 在指定行后插入
            insertPos = doc.line(afterLine).to;
            insertText = '\n' + sortedLines.join('\n');
        }

        view.dispatch({
            changes: { from: insertPos, to: insertPos, insert: insertText }
        });
        console.log('[Injected] Inserted', sortedLines.length, 'lines after line', afterLine);
        return true;
    }

    // 应用修改操作（使用 diff 只更新真正改变的部分）
    function applyModifyEdit(view, lines) {
        const doc = view.state.doc;
        const changes = [];

        for (const [lineNum, newContent] of Object.entries(lines)) {
            const lineNumber = parseInt(lineNum);
            if (lineNumber >= 1 && lineNumber <= doc.lines) {
                const line = doc.line(lineNumber);
                const oldContent = line.text;

                // 使用 calculateLineDiff 计算最小变化
                const change = calculateLineDiff(oldContent, newContent, line.from);

                if (change !== null) {
                    // 只有真正有变化时才添加
                    changes.push(change);
                    console.log(`[Injected] Line ${lineNumber} diff: from=${change.from}, to=${change.to}, insert="${change.insert.substring(0, 30)}..."`);
                } else {
                    console.log(`[Injected] Line ${lineNumber} unchanged, skipping`);
                }
            }
        }

        if (changes.length === 0) {
            console.log('[Injected] No changes needed, all lines unchanged');
            return true; // 没有变化也算成功
        }

        view.dispatch({ changes });
        console.log('[Injected] Modified', changes.length, 'lines with minimal diff');
        return true;
    }

    // 应用编辑
    function applyEdit(edit, view) {
        // 注意：不设置 __overleafReaderExternalUpdate 标志
        // 这样插入/删除操作会被轮询检测到，并触发 DOC_LINE_CHANGED 事件
        // 从而保持中文文档的行数同步

        let result = false;
        switch (edit.type) {
            case 'delete':
                result = applyDeleteEdit(view, edit.startLine, edit.endLine);
                break;
            case 'insert':
                result = applyInsertEdit(view, edit.afterLine, edit.lines);
                break;
            case 'modify':
                result = applyModifyEdit(view, edit.lines);
                break;
            default:
                console.error('[Injected] Unknown edit type:', edit.type);
                result = false;
        }

        return result;
    }

    // 显示编辑确认弹窗（异步版本，支持文件切换）
    window.__overleafReaderShowEditPopupAsync = async function(edit) {
        console.log('[Injected] Showing edit popup:', edit);

        // 注入样式
        injectEditPopupStyles();

        // 移除已有弹窗
        const existingPopup = document.getElementById('overleaf-edit-popup');
        const existingOverlay = document.getElementById('overleaf-edit-popup-overlay');
        if (existingPopup) existingPopup.remove();
        if (existingOverlay) existingOverlay.remove();

        // 如果指定了文件名，先切换到目标文件
        if (edit.fileName) {
            const currentFile = window.__overleafReaderGetCurrentFile();
            console.log('[Injected] Current file:', currentFile, ', Target file:', edit.fileName);

            if (currentFile !== edit.fileName) {
                console.log('[Injected] Switching to target file:', edit.fileName);
                const switched = window.__overleafReaderSwitchToFile(edit.fileName);
                if (!switched) {
                    console.error('[Injected] Failed to switch to file:', edit.fileName);
                    window.postMessage({
                        type: 'OVERLEAF_EDIT_POPUP_RESULT',
                        confirmed: false,
                        success: false,
                        error: `无法切换到文件: ${edit.fileName}`
                    }, '*');
                    return { success: false, error: `Cannot switch to file: ${edit.fileName}` };
                }

                // 等待文件加载完成
                try {
                    await window.__overleafReaderWaitForFileLoad(3000);
                    console.log('[Injected] File loaded successfully:', edit.fileName);
                } catch (err) {
                    console.error('[Injected] Timeout waiting for file load:', err);
                    window.postMessage({
                        type: 'OVERLEAF_EDIT_POPUP_RESULT',
                        confirmed: false,
                        success: false,
                        error: `文件加载超时: ${edit.fileName}`
                    }, '*');
                    return { success: false, error: `File load timeout: ${edit.fileName}` };
                }
            }
        }

        // 获取编辑器视图
        const view = window.overleaf?.unstable?.store?.get('editor.view');
        if (!view || !view.state || !view.state.doc) {
            console.error('[Injected] Cannot get editor view for edit popup');
            window.postMessage({
                type: 'OVERLEAF_EDIT_POPUP_RESULT',
                confirmed: false,
                success: false,
                error: 'Cannot access editor'
            }, '*');
            return { success: false, error: 'Cannot access editor' };
        }

        // 获取目标行并滚动
        const targetLine = getEditTargetLine(edit);
        const doc = view.state.doc;

        if (targetLine >= 1 && targetLine <= doc.lines) {
            const line = doc.line(targetLine);
            view.dispatch({
                selection: { anchor: line.from, head: line.from },
                scrollIntoView: true
            });
        }

        // 延迟显示弹窗（等待滚动完成）
        setTimeout(() => {
            // 重新获取view，因为文件可能已切换
            const currentView = window.overleaf?.unstable?.store?.get('editor.view');
            if (!currentView || !currentView.state || !currentView.state.doc) {
                window.postMessage({
                    type: 'OVERLEAF_EDIT_POPUP_RESULT',
                    confirmed: false,
                    success: false,
                    error: 'Editor view lost after scroll'
                }, '*');
                return;
            }

            const previewHtml = generateEditPreviewHtml(edit, currentView);

            // 创建遮罩层
            const overlay = document.createElement('div');
            overlay.id = 'overleaf-edit-popup-overlay';
            overlay.className = 'overleaf-edit-popup-overlay';

            // 创建弹窗
            const popup = document.createElement('div');
            popup.id = 'overleaf-edit-popup';
            popup.className = 'overleaf-edit-popup';

            const typeLabels = { delete: '删除', insert: '插入', modify: '修改' };
            const typeLabel = typeLabels[edit.type] || edit.type;
            const confirmLabels = { delete: '确认删除', insert: '确认插入', modify: '确认修改' };
            const confirmLabel = confirmLabels[edit.type] || '确认';

            // 显示文件名（如果有）
            const fileNameDisplay = edit.fileName ? `<span class="edit-file-name">${edit.fileName}</span>` : '';

            popup.innerHTML = `
                <div class="overleaf-edit-popup-header">
                    <span class="edit-type-badge ${edit.type}">${typeLabel}</span>
                    ${fileNameDisplay}
                    <span class="edit-popup-title">编辑预览</span>
                    <button class="edit-popup-close" title="关闭">×</button>
                </div>
                <div class="overleaf-edit-popup-content">
                    ${previewHtml}
                </div>
                <div class="overleaf-edit-popup-footer">
                    <button class="edit-popup-cancel">跳过</button>
                    <button class="edit-popup-confirm">${confirmLabel}</button>
                </div>
            `;

            document.body.appendChild(overlay);
            document.body.appendChild(popup);

            // 定位弹窗（居中显示）
            const popupRect = popup.getBoundingClientRect();
            popup.style.top = `${Math.max(50, (window.innerHeight - popupRect.height) / 2)}px`;
            popup.style.left = `${Math.max(50, (window.innerWidth - popupRect.width) / 2)}px`;

            const cleanup = () => {
                popup.remove();
                overlay.remove();
            };

            // 绑定关闭事件
            popup.querySelector('.edit-popup-close').addEventListener('click', () => {
                cleanup();
                window.postMessage({ type: 'OVERLEAF_EDIT_POPUP_RESULT', confirmed: false }, '*');
            });

            popup.querySelector('.edit-popup-cancel').addEventListener('click', () => {
                cleanup();
                window.postMessage({ type: 'OVERLEAF_EDIT_POPUP_RESULT', confirmed: false }, '*');
            });

            overlay.addEventListener('click', () => {
                cleanup();
                window.postMessage({ type: 'OVERLEAF_EDIT_POPUP_RESULT', confirmed: false }, '*');
            });

            // 绑定确认事件
            popup.querySelector('.edit-popup-confirm').addEventListener('click', () => {
                const confirmBtn = popup.querySelector('.edit-popup-confirm');
                confirmBtn.disabled = true;
                confirmBtn.textContent = '应用中...';

                try {
                    // 使用当前的view
                    const latestView = window.overleaf?.unstable?.store?.get('editor.view');
                    const success = applyEdit(edit, latestView);

                    // 注意：不再发送 AMBIENT_EDIT_SYNC_TO_ZH 消息
                    // 插入/删除操作会通过轮询检测触发 DOC_LINE_CHANGED 事件
                    // 从而自动保持中文文档的行数同步（插入空行/删除行）

                    cleanup();
                    window.postMessage({
                        type: 'OVERLEAF_EDIT_POPUP_RESULT',
                        confirmed: true,
                        success: success
                    }, '*');
                } catch (error) {
                    console.error('[Injected] Error applying edit:', error);
                    cleanup();
                    window.postMessage({
                        type: 'OVERLEAF_EDIT_POPUP_RESULT',
                        confirmed: true,
                        success: false,
                        error: error.message
                    }, '*');
                }
            });
        }, 200);

        return { success: true };
    };

    // 同步版本的包装器（保持向后兼容）
    window.__overleafReaderShowEditPopup = function(edit) {
        window.__overleafReaderShowEditPopupAsync(edit);
        return { success: true };
    };

    // 监听编辑弹窗消息
    window.addEventListener('message', function(event) {
        if (event.data && event.data.type === 'OVERLEAF_READER_SHOW_EDIT_POPUP') {
            const result = window.__overleafReaderShowEditPopup(event.data.edit);
            window.postMessage({
                type: 'OVERLEAF_READER_SHOW_EDIT_POPUP_RESULT',
                ...result
            }, '*');
        }
    });

    // =================== 拖拽功能支持（氛围写作） ===================

    /**
     * 获取当前编辑器选区的行号信息
     * 返回格式化的 {"文件名": {"行号": "内容", ...}} 数据
     * @returns {object} 包含完整数据的对象
     */
    window.__overleafReaderGetSelectionLineInfo = function() {
        const result = {
            data: {},  // {"文件名": {"行号": "内容", ...}} 格式
            fileName: '',
            startLine: 0,
            endLine: 0
        };

        try {
            // 获取当前文件名
            const fileName = window.__overleafReaderGetCurrentFile() || 'unknown';
            result.fileName = fileName;

            // 获取编辑器视图
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) {
                console.log('[Overleaf Reader Injected] Cannot get editor view for selection');
                return result;
            }

            const state = view.state;
            const selection = state.selection.main;

            // 如果没有选区，返回空结果
            if (selection.from === selection.to) {
                console.log('[Overleaf Reader Injected] No selection');
                return result;
            }

            // 获取选区的起始和结束行号
            const startLine = state.doc.lineAt(selection.from).number;
            const endLine = state.doc.lineAt(selection.to).number;

            result.startLine = startLine;
            result.endLine = endLine;

            // 获取选中的文本，然后按换行符分割
            const selectedText = state.sliceDoc(selection.from, selection.to);
            const lines = selectedText.split('\n');

            // 构建 {"文件名": {"行号": "内容", ...}} 格式的数据
            const linesData = {};
            for (let i = 0; i < lines.length; i++) {
                const lineNum = startLine + i;
                linesData[lineNum.toString()] = lines[i];
            }
            result.data[fileName] = linesData;

            console.log('[Overleaf Reader Injected] Selection line info:', result);
            return result;

        } catch (err) {
            console.error('[Overleaf Reader Injected] Error getting selection line info:', err);
            return result;
        }
    };

    // 监听获取选区行号请求
    window.addEventListener('message', function(event) {
        if (event.data && event.data.type === 'OVERLEAF_READER_GET_SELECTION_LINE_INFO') {
            const lineInfo = window.__overleafReaderGetSelectionLineInfo();
            window.postMessage({
                type: 'OVERLEAF_READER_SELECTION_LINE_INFO_RESPONSE',
                ...lineInfo
            }, '*');
        }
    });

    // =================== 氛围写作按钮（在 Add comment 旁边） ===================

    /**
     * 获取选区覆盖的完整行内容
     * 即使只选中部分行，也返回完整的行内容
     * @returns {object} {"文件名": {"行号": "完整行内容", ...}}
     */
    function getSelectedLinesFullContent() {
        const result = {};

        try {
            const fileName = window.__overleafReaderGetCurrentFile() || 'unknown';
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) {
                console.log('[Overleaf Reader Injected] Cannot get editor view');
                return result;
            }

            const state = view.state;
            const selection = state.selection.main;

            if (selection.from === selection.to) {
                console.log('[Overleaf Reader Injected] No selection for ambient writing');
                return result;
            }

            // 获取选区覆盖的行范围
            const startLine = state.doc.lineAt(selection.from);
            const endLine = state.doc.lineAt(selection.to);

            // 构建完整行内容
            const linesData = {};
            for (let lineNum = startLine.number; lineNum <= endLine.number; lineNum++) {
                const line = state.doc.line(lineNum);
                linesData[lineNum.toString()] = line.text;
            }

            result[fileName] = linesData;
            console.log('[Overleaf Reader Injected] Selected full lines:', result);
            return result;

        } catch (err) {
            console.error('[Overleaf Reader Injected] Error getting selected lines:', err);
            return result;
        }
    }

    /**
     * 获取当前选中的纯文本
     */
    function getSelectedText() {
        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) return '';

            const state = view.state;
            const selection = state.selection.main;

            if (selection.from === selection.to) return '';

            return state.sliceDoc(selection.from, selection.to);
        } catch (err) {
            console.error('[Overleaf Reader Injected] Error getting selected text:', err);
            return '';
        }
    }

    /**
     * 创建"插入氛围写作"按钮
     */
    function createAmbientWritingButton() {
        const btn = document.createElement('button');
        btn.className = 'review-tooltip-menu-button';
        btn.setAttribute('data-ambient-writing', 'true');
        btn.innerHTML = `
            <span class="material-symbols">edit_note</span>
            <span class="review-tooltip-menu-button-label">插入氛围写作</span>
        `;
        btn.style.cssText = 'display: flex; align-items: center; gap: 4px; padding: 4px 8px; border: none; background: transparent; cursor: pointer; font-size: 13px; color: inherit; white-space: nowrap;';

        btn.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            const linesData = getSelectedLinesFullContent();
            if (Object.keys(linesData).length > 0) {
                console.log('[Overleaf Reader Injected] Sending lines to ambient writing:', linesData);
                window.postMessage({
                    type: 'OVERLEAF_INSERT_TO_AMBIENT_WRITING',
                    data: linesData
                }, '*');
            }
        });

        return btn;
    }

    /**
     * 创建"自动引用"按钮
     */
    function createAutoCiteButton() {
        const btn = document.createElement('button');
        btn.className = 'review-tooltip-menu-button';
        btn.setAttribute('data-auto-cite', 'true');
        btn.innerHTML = `
            <span class="material-symbols">format_quote</span>
            <span class="review-tooltip-menu-button-label">自动引用</span>
        `;
        btn.style.cssText = 'display: flex; align-items: center; gap: 4px; padding: 4px 8px; border: none; background: transparent; cursor: pointer; font-size: 13px; color: inherit; white-space: nowrap;';

        btn.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            const selectedText = getSelectedText();
            if (selectedText) {
                console.log('[Overleaf Reader Injected] Triggering auto-cite with:', selectedText);
                window.postMessage({
                    type: 'OVERLEAF_AUTO_CITE',
                    selectedText: selectedText
                }, '*');
            }
        });

        return btn;
    }

    /**
     * 创建"语法检查"按钮
     */
    function createGrammarCheckButton() {
        const btn = document.createElement('button');
        btn.className = 'review-tooltip-menu-button';
        btn.setAttribute('data-grammar-check', 'true');
        btn.innerHTML = `
            <span class="material-symbols">spellcheck</span>
            <span class="review-tooltip-menu-button-label">语法检查</span>
        `;
        btn.style.cssText = 'display: flex; align-items: center; gap: 4px; padding: 4px 8px; border: none; background: transparent; cursor: pointer; font-size: 13px; color: inherit; white-space: nowrap;';

        btn.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            const linesData = getSelectedLinesFullContent();
            if (Object.keys(linesData).length > 0) {
                console.log('[Overleaf Reader Injected] Triggering grammar check:', linesData);
                window.postMessage({
                    type: 'OVERLEAF_GRAMMAR_CHECK',
                    data: linesData
                }, '*');
            }
        });

        return btn;
    }

    /**
     * 创建"一键润色"按钮
     */
    function createPolishButton() {
        const btn = document.createElement('button');
        btn.className = 'review-tooltip-menu-button';
        btn.setAttribute('data-polish', 'true');
        btn.innerHTML = `
            <span class="material-symbols">auto_fix_high</span>
            <span class="review-tooltip-menu-button-label">一键润色</span>
        `;
        btn.style.cssText = 'display: flex; align-items: center; gap: 4px; padding: 4px 8px; border: none; background: transparent; cursor: pointer; font-size: 13px; color: inherit; white-space: nowrap;';

        btn.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            const linesData = getSelectedLinesFullContent();
            if (Object.keys(linesData).length > 0) {
                console.log('[Overleaf Reader Injected] Triggering polish:', linesData);
                window.postMessage({
                    type: 'OVERLEAF_POLISH',
                    data: linesData
                }, '*');
            }
        });

        return btn;
    }

    /**
     * 定期检查并添加按钮到 Add comment 旁边
     */
    function setupTooltipButtons() {
        setInterval(() => {
            // 查找 review-tooltip-menu，且还没有添加我们的按钮
            const menu = document.querySelector('.review-tooltip-menu');
            if (menu) {
                // 添加氛围写作按钮
                if (!menu.querySelector('[data-ambient-writing]')) {
                    const ambientBtn = createAmbientWritingButton();
                    menu.appendChild(ambientBtn);
                    console.log('[Overleaf Reader Injected] Added ambient writing button');
                }
                // 添加自动引用按钮
                if (!menu.querySelector('[data-auto-cite]')) {
                    const citeBtn = createAutoCiteButton();
                    menu.appendChild(citeBtn);
                    console.log('[Overleaf Reader Injected] Added auto-cite button');
                }
                // 添加语法检查按钮
                if (!menu.querySelector('[data-grammar-check]')) {
                    const grammarBtn = createGrammarCheckButton();
                    menu.appendChild(grammarBtn);
                    console.log('[Overleaf Reader Injected] Added grammar check button');
                }
                // 添加一键润色按钮
                if (!menu.querySelector('[data-polish]')) {
                    const polishBtn = createPolishButton();
                    menu.appendChild(polishBtn);
                    console.log('[Overleaf Reader Injected] Added polish button');
                }
            }
        }, 500);
    }

    setupTooltipButtons();

    // =================== 文件树右键菜单增强 ===================

    /**
     * 获取选中文件的信息（从 Overleaf 的 React 状态中）
     */
    function getSelectedFileInfo() {
        try {
            console.log('[Overleaf Reader Injected] getSelectedFileInfo called');

            // 方法1：从 Overleaf 的全局 store 获取选中文件
            if (window.overleaf && window.overleaf.unstable && window.overleaf.unstable.store) {
                const store = window.overleaf.unstable.store;

                // 尝试获取文件树选中状态
                const fileTreeData = store.get('file-tree.selected');
                if (fileTreeData) {
                    console.log('[Overleaf Reader Injected] Got file selection from store:', fileTreeData);
                    return fileTreeData;
                }
            }

            // 方法2：从 DOM 中获取选中的文件信息
            // Overleaf 结构: li[aria-selected="true"] > div.entity[data-file-id]
            const selectedItem = document.querySelector('.file-tree-inner li.selected, .file-tree-inner li[aria-selected="true"]');
            console.log('[Overleaf Reader Injected] selectedItem:', selectedItem);

            if (selectedItem) {
                // 首先尝试从子元素 .entity 获取 data-file-id
                const entityDiv = selectedItem.querySelector('.entity[data-file-id]');
                console.log('[Overleaf Reader Injected] entityDiv:', entityDiv);

                if (entityDiv) {
                    const fileId = entityDiv.getAttribute('data-file-id');
                    const fileType = entityDiv.getAttribute('data-file-type');
                    // 从 aria-label 或 .item-name-button span 获取文件名
                    const fileName = selectedItem.getAttribute('aria-label') ||
                                     selectedItem.querySelector('.item-name-button span')?.textContent?.trim();

                    console.log('[Overleaf Reader Injected] fileId:', fileId, 'fileName:', fileName, 'fileType:', fileType);

                    if (fileId && fileName) {
                        console.log('[Overleaf Reader Injected] Got file info from DOM:', { id: fileId, name: fileName, type: fileType });
                        return {
                            id: fileId,
                            name: fileName,
                            type: fileType || 'doc'
                        };
                    }
                }

                // 尝试从 React fiber 获取文件信息
                const keys = Object.keys(selectedItem);
                const reactKey = keys.find(key => key.startsWith('__reactFiber') || key.startsWith('__reactInternalInstance'));
                if (reactKey) {
                    let fiber = selectedItem[reactKey];
                    let depth = 0;
                    while (fiber && depth < 30) {
                        if (fiber.memoizedProps) {
                            const props = fiber.memoizedProps;
                            // 查找文件相关的属性
                            if (props.id && (props.name || props.fileName)) {
                                console.log('[Overleaf Reader Injected] Found file info from React fiber:', props);
                                return {
                                    id: props.id,
                                    name: props.name || props.fileName,
                                    type: props.type || 'file',
                                    hash: props.hash
                                };
                            }
                            // 也可能在 entity 属性中
                            if (props.entity) {
                                console.log('[Overleaf Reader Injected] Found entity from React fiber:', props.entity);
                                return {
                                    id: props.entity._id,
                                    name: props.entity.name,
                                    type: props.entity.type || 'file',
                                    hash: props.entity.hash
                                };
                            }
                        }
                        fiber = fiber.return;
                        depth++;
                    }
                }

                // 备用：从 DOM 属性获取
                const fileId = selectedItem.getAttribute('data-file-id') || selectedItem.getAttribute('data-entity-id');
                const fileName = selectedItem.textContent?.trim();
                if (fileId || fileName) {
                    return { id: fileId, name: fileName };
                }
            }

            return null;
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error getting selected file info:', e);
            return null;
        }
    }

    /**
     * 获取当前项目 ID
     */
    function getProjectId() {
        const match = window.location.pathname.match(/\/project\/([a-f0-9]+)/);
        return match ? match[1] : null;
    }

    /**
     * 创建"插入到氛围写作"菜单项（用于文件树右键菜单）
     * @param {Object} capturedFileInfo - 在菜单创建时捕获的文件信息
     */
    function createFileTreeAmbientMenuItem(capturedFileInfo) {
        const menuItem = document.createElement('li');
        menuItem.setAttribute('role', 'none');
        menuItem.setAttribute('data-ambient-file-menu', 'true');

        const button = document.createElement('button');
        button.className = 'dropdown-item';
        button.setAttribute('role', 'menuitem');
        button.type = 'button';
        button.textContent = '插入到氛围写作';
        button.style.cssText = 'width: 100%; text-align: left; padding: 6px 20px;';

        // 使用闭包保存创建菜单时的文件信息
        const fileInfo = capturedFileInfo;
        const projectId = getProjectId();

        button.addEventListener('click', async function(e) {
            e.preventDefault();
            e.stopPropagation();

            console.log('[Overleaf Reader Injected] File tree ambient writing clicked:', { fileInfo, projectId });

            if (fileInfo && projectId) {
                // 判断文件类型
                const fileName = fileInfo.name || '';
                const fileType = fileInfo.type || 'doc';

                // Overleaf 原生支持的文档类型（使用 /doc/ API）
                const isOverleafDoc = fileType === 'doc';

                // 代码/文本文件扩展名（Overleaf 不认为是 doc，但实际是文本，需要用 /file/ API 下载后解码）
                const codeTextExtensions = /\.(py|pyw|r|R|sh|bash|zsh|js|mjs|cjs|ts|tsx|jsx|c|cpp|cc|cxx|h|hpp|hxx|java|kt|kts|scala|rb|pl|pm|php|lua|m|mm|swift|go|rs|zig|nim|jl|f90|f95|f03|sql|html|htm|css|scss|sass|less|vue|svelte|yaml|yml|toml|ini|cfg|conf|env|gitignore|dockerignore|makefile|cmake|gradle|ps1|bat|cmd|awk|sed|tcl|v|sv|vhd|vhdl|asm|s|lisp|cl|el|scm|rkt|hs|ml|mli|fs|fsi|fsx|ex|exs|erl|hrl|clj|cljs|cljc|dart|groovy|perl|tcsh|fish|nu)$/i.test(fileName);

                // LaTeX 相关文本文件（通常 Overleaf 认为是 doc）
                const latexTextExtensions = /\.(tex|txt|bib|bst|cls|sty|md|json|xml|csv|log|aux|toc|lof|lot|bbl|blg)$/i.test(fileName);

                const isImageFile = /\.(png|jpg|jpeg|gif|bmp|webp|svg)$/i.test(fileName);
                const isPdfFile = /\.pdf$/i.test(fileName);

                try {
                    if (isOverleafDoc || latexTextExtensions) {
                        // Overleaf 原生文档：使用 /doc/ API 获取文本内容
                        const downloadUrl = `/project/${projectId}/doc/${fileInfo.id}/download`;
                        const response = await fetch(downloadUrl);
                        if (response.ok) {
                            const content = await response.text();

                            window.postMessage({
                                type: 'OVERLEAF_INSERT_FILE_TO_AMBIENT_WRITING',
                                data: {
                                    fileName: fileInfo.name,
                                    fileId: fileInfo.id,
                                    content: content,
                                    contentType: 'text',
                                    projectId: projectId
                                }
                            }, '*');

                            console.log('[Overleaf Reader Injected] Text file content sent to ambient writing');
                        } else {
                            console.error('[Overleaf Reader Injected] Failed to fetch text file:', response.status);
                        }
                    } else if (codeTextExtensions) {
                        // 代码文件：Overleaf 当作二进制存储，但实际是文本
                        // 使用 /file/ API 下载后解码为文本
                        const downloadUrl = `/project/${projectId}/file/${fileInfo.id}`;
                        const response = await fetch(downloadUrl);
                        if (response.ok) {
                            const blob = await response.blob();
                            // 直接解码为文本（UTF-8）
                            const content = await blob.text();

                            window.postMessage({
                                type: 'OVERLEAF_INSERT_FILE_TO_AMBIENT_WRITING',
                                data: {
                                    fileName: fileInfo.name,
                                    fileId: fileInfo.id,
                                    content: content,
                                    contentType: 'text',
                                    projectId: projectId
                                }
                            }, '*');

                            console.log('[Overleaf Reader Injected] Code file content sent to ambient writing (decoded from binary)');
                        } else {
                            console.error('[Overleaf Reader Injected] Failed to fetch code file:', response.status);
                        }
                    } else if (isPdfFile) {
                        // PDF 文件：下载二进制，标记为 pdf 类型，后端会转换为图像
                        const downloadUrl = `/project/${projectId}/file/${fileInfo.id}`;
                        const response = await fetch(downloadUrl);
                        if (response.ok) {
                            const blob = await response.blob();
                            const reader = new FileReader();

                            reader.onloadend = function() {
                                let base64Data = reader.result; // data:application/octet-stream;base64,...

                                // 修正 MIME 类型为 application/pdf
                                if (base64Data.startsWith('data:application/octet-stream;base64,')) {
                                    base64Data = base64Data.replace('data:application/octet-stream;base64,', 'data:application/pdf;base64,');
                                }

                                window.postMessage({
                                    type: 'OVERLEAF_INSERT_FILE_TO_AMBIENT_WRITING',
                                    data: {
                                        fileName: fileInfo.name,
                                        fileId: fileInfo.id,
                                        content: base64Data,
                                        contentType: 'pdf',
                                        mimeType: 'application/pdf',
                                        projectId: projectId
                                    }
                                }, '*');

                                console.log('[Overleaf Reader Injected] PDF file (base64) sent to ambient writing');
                            };

                            reader.readAsDataURL(blob);
                        } else {
                            console.error('[Overleaf Reader Injected] Failed to fetch PDF file:', response.status);
                        }
                    } else if (isImageFile) {
                        // 图片文件：获取二进制内容并转为 base64
                        const downloadUrl = `/project/${projectId}/file/${fileInfo.id}`;
                        const response = await fetch(downloadUrl);
                        if (response.ok) {
                            const blob = await response.blob();
                            const reader = new FileReader();

                            // 根据文件扩展名确定正确的 MIME 类型
                            const ext = fileName.split('.').pop().toLowerCase();
                            const mimeTypeMap = {
                                'png': 'image/png',
                                'jpg': 'image/jpeg',
                                'jpeg': 'image/jpeg',
                                'gif': 'image/gif',
                                'bmp': 'image/bmp',
                                'webp': 'image/webp',
                                'svg': 'image/svg+xml'
                            };
                            const correctMimeType = mimeTypeMap[ext] || 'image/png';

                            reader.onloadend = function() {
                                let base64Data = reader.result; // 包含 data:xxx;base64, 前缀

                                // 替换错误的 MIME 类型（Overleaf 服务器可能返回 application/octet-stream）
                                if (base64Data.startsWith('data:application/octet-stream;base64,')) {
                                    base64Data = base64Data.replace('data:application/octet-stream;base64,', `data:${correctMimeType};base64,`);
                                    console.log('[Overleaf Reader Injected] Fixed MIME type to:', correctMimeType);
                                }

                                window.postMessage({
                                    type: 'OVERLEAF_INSERT_FILE_TO_AMBIENT_WRITING',
                                    data: {
                                        fileName: fileInfo.name,
                                        fileId: fileInfo.id,
                                        content: base64Data,
                                        contentType: 'image',
                                        mimeType: correctMimeType,
                                        projectId: projectId
                                    }
                                }, '*');

                                console.log('[Overleaf Reader Injected] Image file (base64) sent to ambient writing, mimeType:', correctMimeType);
                            };

                            reader.readAsDataURL(blob);
                        } else {
                            console.error('[Overleaf Reader Injected] Failed to fetch image file:', response.status);
                        }
                    } else {
                        // 其他二进制文件：发送引用标记
                        window.postMessage({
                            type: 'OVERLEAF_INSERT_FILE_TO_AMBIENT_WRITING',
                            data: {
                                fileName: fileInfo.name,
                                fileId: fileInfo.id,
                                content: `[二进制文件: ${fileInfo.name}]`,
                                contentType: 'binary',
                                projectId: projectId
                            }
                        }, '*');

                        console.log('[Overleaf Reader Injected] Binary file reference sent to ambient writing');
                    }
                } catch (error) {
                    console.error('[Overleaf Reader Injected] Error fetching file:', error);
                }
            }

            // 关闭菜单
            const menu = button.closest('.dropdown-menu');
            if (menu) {
                menu.classList.remove('show');
            }
        });

        menuItem.appendChild(button);
        return menuItem;
    }

    /**
     * 监听文件树右键菜单并添加自定义按钮
     */
    function setupFileTreeContextMenu() {
        // 使用 MutationObserver 监听右键菜单的出现
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        // 查找文件树右键菜单
                        // Overleaf 的菜单通常是 dropdown-menu，且在 file-tree 区域内
                        let dropdownMenu = null;

                        if (node.classList?.contains('dropdown-menu')) {
                            dropdownMenu = node;
                        } else if (node.querySelector) {
                            dropdownMenu = node.querySelector('.dropdown-menu');
                        }

                        if (dropdownMenu && !dropdownMenu.querySelector('[data-ambient-file-menu]')) {
                            // 检查是否是文件树的右键菜单（通过查找 Download 菜单项）
                            const downloadItem = Array.from(dropdownMenu.querySelectorAll('a, button'))
                                .find(el => el.textContent?.toLowerCase().includes('download') ||
                                           el.getAttribute('download') !== null);

                            if (downloadItem) {
                                console.log('[Overleaf Reader Injected] Found file tree context menu with Download button');

                                // 方法1: 查找当前展开的菜单按钮 (aria-expanded="true")
                                // 菜单按钮 ID 格式: menu-button-{fileId}
                                let fileInfo = null;
                                const expandedMenuBtn = document.querySelector('.file-tree-inner button.entity-menu-toggle[aria-expanded="true"]');
                                console.log('[Overleaf Reader Injected] Expanded menu button:', expandedMenuBtn);

                                if (expandedMenuBtn) {
                                    const btnId = expandedMenuBtn.id; // menu-button-{fileId}
                                    console.log('[Overleaf Reader Injected] Button ID:', btnId);

                                    if (btnId && btnId.startsWith('menu-button-')) {
                                        const fileId = btnId.replace('menu-button-', '');
                                        // 通过 fileId 找到对应的文件元素
                                        const entityDiv = document.querySelector(`.entity[data-file-id="${fileId}"]`);
                                        console.log('[Overleaf Reader Injected] Found entity by fileId:', entityDiv);

                                        if (entityDiv) {
                                            const fileType = entityDiv.getAttribute('data-file-type');
                                            const liElement = entityDiv.closest('li[role="treeitem"]');
                                            const fileName = liElement?.getAttribute('aria-label') ||
                                                             entityDiv.querySelector('.item-name-button span')?.textContent?.trim();
                                            if (fileId && fileName) {
                                                fileInfo = { id: fileId, name: fileName, type: fileType || 'doc' };
                                            }
                                        }
                                    }
                                }

                                // 如果上面方法失败，尝试从选中状态获取
                                if (!fileInfo) {
                                    fileInfo = getSelectedFileInfo();
                                }

                                console.log('[Overleaf Reader Injected] Captured file info at menu creation:', fileInfo);

                                // 在 Download 按钮后面插入我们的按钮
                                const downloadLi = downloadItem.closest('li');
                                if (downloadLi) {
                                    const ambientMenuItem = createFileTreeAmbientMenuItem(fileInfo);
                                    downloadLi.insertAdjacentElement('afterend', ambientMenuItem);
                                    console.log('[Overleaf Reader Injected] Added ambient writing menu item after Download');
                                }
                            }
                        }
                    }
                }
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        console.log('[Overleaf Reader Injected] File tree context menu observer set up');
    }

    setupFileTreeContextMenu();

    // =================== 编译错误修复按钮（在 Suggest fix 按钮旁边） ===================

    /**
     * 获取编译日志内容
     * @returns {string} 编译日志文本
     */
    function getCompileLog() {
        try {
            // 方法1: 从日志面板获取
            const logPane = document.querySelector('.logs-pane');
            if (logPane) {
                // 获取所有日志条目
                const logEntries = logPane.querySelectorAll('.log-entry, .log-entry-content, .log-entry-formatted-content');
                if (logEntries.length > 0) {
                    const logs = Array.from(logEntries).map(entry => entry.textContent || '').join('\n');
                    if (logs.trim()) {
                        console.log('[Overleaf Reader Injected] Got compile log from log pane, length:', logs.length);
                        return logs;
                    }
                }
            }

            // 方法2: 从 raw log 获取
            const rawLog = document.querySelector('.raw-log, .raw-log-content, pre.log-output');
            if (rawLog) {
                const logText = rawLog.textContent || '';
                console.log('[Overleaf Reader Injected] Got compile log from raw log, length:', logText.length);
                return logText;
            }

            // 方法3: 从所有可见的日志元素获取
            const allLogElements = document.querySelectorAll('[class*="log"], [class*="error"], [class*="warning"]');
            const combinedLog = Array.from(allLogElements)
                .filter(el => el.closest('.logs-pane') || el.closest('[class*="preview"]'))
                .map(el => el.textContent || '')
                .join('\n');

            if (combinedLog.trim()) {
                console.log('[Overleaf Reader Injected] Got compile log from combined elements, length:', combinedLog.length);
                return combinedLog;
            }

            console.log('[Overleaf Reader Injected] No compile log found');
            return '';
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error getting compile log:', e);
            return '';
        }
    }

    /**
     * 从错误条目元素获取错误信息
     * @param {HTMLElement} logEntry - 日志条目元素
     * @returns {Object} 错误信息对象
     */
    function getErrorInfoFromLogEntry(logEntry) {
        try {
            const result = {
                message: '',
                file: '',
                line: 0,
                rawContent: ''
            };

            // 获取错误消息
            const messageEl = logEntry.querySelector('.log-entry-header-title, .log-entry-title, [class*="title"]');
            if (messageEl) {
                result.message = messageEl.textContent?.trim() || '';
            }

            // 获取文件名和行号
            const locationEl = logEntry.querySelector('.log-entry-header-link, [class*="location"], [class*="file"]');
            if (locationEl) {
                const locationText = locationEl.textContent || '';
                // 解析格式如 "main.tex, line 42" 或 "main.tex:42"
                const match = locationText.match(/([^,:\s]+\.(tex|bib|sty|cls))[,:\s]*(?:line\s*)?(\d+)?/i);
                if (match) {
                    result.file = match[1];
                    result.line = match[3] ? parseInt(match[3]) : 0;
                }
            }

            // 获取原始内容
            const contentEl = logEntry.querySelector('.log-entry-content, .log-entry-formatted-content, pre');
            if (contentEl) {
                result.rawContent = contentEl.textContent?.trim() || '';
            }

            // 如果没有获取到消息，使用整个条目的文本
            if (!result.message && !result.rawContent) {
                result.rawContent = logEntry.textContent?.trim() || '';
            }

            console.log('[Overleaf Reader Injected] Extracted error info:', result);
            return result;
        } catch (e) {
            console.error('[Overleaf Reader Injected] Error extracting error info:', e);
            return { message: '', file: '', line: 0, rawContent: logEntry.textContent || '' };
        }
    }

    /**
     * 创建"文智云修复"按钮
     * @param {HTMLElement} logEntry - 日志条目元素
     */
    function createWenzhiyunFixButton(logEntry) {
        const btn = document.createElement('button');
        btn.className = 'btn btn-secondary wenzhiyun-fix-btn';
        btn.setAttribute('data-wenzhiyun-fix', 'true');
        btn.innerHTML = `
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right: 4px;">
                <path d="M12 2L2 7L12 12L22 7L12 2Z" fill="currentColor"/>
                <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span>文智云修复</span>
        `;
        btn.style.cssText = `
            display: inline-flex;
            align-items: center;
            padding: 4px 10px;
            margin-left: 8px;
            font-size: 12px;
            border-radius: 4px;
            background-color: #7c3aed;
            border: 1px solid #7c3aed;
            color: white;
            cursor: pointer;
            transition: all 0.2s;
        `;
        btn.title = '使用文智云AI修复此编译错误';

        // 悬停效果
        btn.addEventListener('mouseenter', () => {
            btn.style.backgroundColor = '#6d28d9';
            btn.style.borderColor = '#6d28d9';
        });
        btn.addEventListener('mouseleave', () => {
            btn.style.backgroundColor = '#7c3aed';
            btn.style.borderColor = '#7c3aed';
        });

        // 点击事件
        btn.addEventListener('click', async function(e) {
            e.preventDefault();
            e.stopPropagation();

            console.log('[Overleaf Reader Injected] 文智云修复 button clicked');

            // 禁用按钮，显示加载状态
            btn.disabled = true;
            const originalText = btn.innerHTML;
            btn.innerHTML = `
                <svg width="14" height="14" viewBox="0 0 24 24" class="animate-spin" style="margin-right: 4px; animation: spin 1s linear infinite;">
                    <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" fill="none" stroke-dasharray="32" stroke-linecap="round"/>
                </svg>
                <span>修复中...</span>
            `;

            try {
                // 获取错误信息
                const errorInfo = getErrorInfoFromLogEntry(logEntry);

                // 获取当前文件内容
                const currentContent = window.__overleafReaderGetContent();
                const currentFile = window.__overleafReaderGetCurrentFile() || 'unknown.tex';

                // 获取完整编译日志
                const compileLog = getCompileLog();

                // 发送消息给 content.js
                window.postMessage({
                    type: 'OVERLEAF_WENZHIYUN_FIX_ERROR',
                    data: {
                        errorInfo: errorInfo,
                        currentFile: currentFile,
                        currentContent: currentContent,
                        compileLog: compileLog
                    }
                }, '*');

                console.log('[Overleaf Reader Injected] Sent fix request to content script');

            } catch (error) {
                console.error('[Overleaf Reader Injected] Error in 文智云修复:', error);
                btn.disabled = false;
                btn.innerHTML = originalText;
            }
        });

        // 添加旋转动画样式
        if (!document.getElementById('wenzhiyun-spin-style')) {
            const style = document.createElement('style');
            style.id = 'wenzhiyun-spin-style';
            style.textContent = `
                @keyframes spin {
                    from { transform: rotate(0deg); }
                    to { transform: rotate(360deg); }
                }
                .wenzhiyun-fix-btn:disabled {
                    opacity: 0.7;
                    cursor: not-allowed;
                }
            `;
            document.head.appendChild(style);
        }

        return btn;
    }

    /**
     * 监听日志面板并添加文智云修复按钮
     */
    function setupCompileErrorButtons() {
        // 使用 MutationObserver 监听日志面板的变化
        const observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                // 检查新添加的节点
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        // 查找日志条目
                        const logEntries = node.querySelectorAll ?
                            node.querySelectorAll('.log-entry, [class*="PreviewLogsPaneEntry"]') : [];

                        // 如果节点本身是日志条目
                        if (node.classList && (node.classList.contains('log-entry') ||
                            node.className?.includes('PreviewLogsPaneEntry'))) {
                            processLogEntry(node);
                        }

                        // 处理子节点中的日志条目
                        logEntries.forEach(entry => processLogEntry(entry));
                    }
                }
            }
        });

        function processLogEntry(logEntry) {
            // 检查是否已经添加了按钮
            if (logEntry.querySelector('[data-wenzhiyun-fix]')) {
                return;
            }

            // 查找 Suggest fix 按钮或按钮容器
            const suggestFixBtn = logEntry.querySelector('button[class*="suggest"], [class*="ai-error-assistant"], [class*="get-help"]');
            const buttonContainer = logEntry.querySelector('.log-entry-header-actions, [class*="actions"], [class*="buttons"]');

            // 检查是否是错误或警告类型的日志
            const isError = logEntry.classList.contains('log-entry-error') ||
                           logEntry.className?.includes('error') ||
                           logEntry.querySelector('[class*="error"]');
            const isWarning = logEntry.classList.contains('log-entry-warning') ||
                             logEntry.className?.includes('warning');

            if (isError || isWarning) {
                const wenzhiyunBtn = createWenzhiyunFixButton(logEntry);

                if (suggestFixBtn) {
                    // 在 Suggest fix 按钮后面插入
                    suggestFixBtn.insertAdjacentElement('afterend', wenzhiyunBtn);
                    console.log('[Overleaf Reader Injected] Added 文智云修复 button after Suggest fix');
                } else if (buttonContainer) {
                    // 添加到按钮容器
                    buttonContainer.appendChild(wenzhiyunBtn);
                    console.log('[Overleaf Reader Injected] Added 文智云修复 button to actions container');
                } else {
                    // 添加到日志条目头部
                    const header = logEntry.querySelector('.log-entry-header, [class*="header"]');
                    if (header) {
                        header.appendChild(wenzhiyunBtn);
                        console.log('[Overleaf Reader Injected] Added 文智云修复 button to log entry header');
                    }
                }
            }
        }

        // 初始处理已存在的日志条目
        function processExistingLogEntries() {
            const logEntries = document.querySelectorAll('.log-entry, [class*="PreviewLogsPaneEntry"]');
            logEntries.forEach(entry => processLogEntry(entry));
        }

        // 监听整个文档
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // 延迟处理已存在的条目
        setTimeout(processExistingLogEntries, 1000);
        setTimeout(processExistingLogEntries, 3000);

        console.log('[Overleaf Reader Injected] Compile error buttons observer set up');
    }

    // 监听修复结果消息
    window.addEventListener('message', function(event) {
        if (event.data && event.data.type === 'OVERLEAF_WENZHIYUN_FIX_RESULT') {
            console.log('[Overleaf Reader Injected] Received fix result:', event.data);

            // 恢复所有禁用的按钮
            const buttons = document.querySelectorAll('.wenzhiyun-fix-btn[disabled]');
            buttons.forEach(btn => {
                btn.disabled = false;
                btn.innerHTML = `
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right: 4px;">
                        <path d="M12 2L2 7L12 12L22 7L12 2Z" fill="currentColor"/>
                        <path d="M2 17L12 22L22 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                        <path d="M2 12L12 17L22 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>
                    <span>文智云修复</span>
                `;
            });

            if (event.data.success) {
                console.log('[Overleaf Reader Injected] Fix applied successfully');
            } else {
                console.error('[Overleaf Reader Injected] Fix failed:', event.data.error);
            }
        }
    });

    setupCompileErrorButtons();

    // =================== 自动续写图标功能 ===================

    // AI 模型错误的建议提示
    const AI_MODEL_ERROR_HINT_CONTINUE = '\n💡 建议：尝试更高级的模型或更高的思考程度';

    /**
     * 显示临时错误提示（在编辑器右上角）
     */
    function showContinueWritingError(message) {
        // 移除已有的错误提示
        const existing = document.getElementById('continue-writing-error-toast');
        if (existing) existing.remove();

        const toast = document.createElement('div');
        toast.id = 'continue-writing-error-toast';
        toast.style.cssText = `
            position: fixed;
            top: 60px;
            right: 20px;
            max-width: 320px;
            padding: 12px 16px;
            background: #fef2f2;
            border: 1px solid #fecaca;
            border-radius: 8px;
            color: #dc2626;
            font-size: 13px;
            line-height: 1.5;
            z-index: 10000;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            white-space: pre-wrap;
        `;
        toast.textContent = message;
        document.body.appendChild(toast);

        // 5秒后自动消失
        setTimeout(() => {
            if (toast.parentNode) {
                toast.style.opacity = '0';
                toast.style.transition = 'opacity 0.3s';
                setTimeout(() => toast.remove(), 300);
            }
        }, 5000);
    }

    /**
     * 注入续写图标样式
     */
    function injectContinueWritingStyles() {
        if (document.getElementById('continue-writing-icon-styles')) return;

        const style = document.createElement('style');
        style.id = 'continue-writing-icon-styles';
        style.textContent = `
            .continue-writing-icon {
                position: absolute;
                display: flex;
                align-items: center;
                justify-content: center;
                width: 22px;
                height: 18px;
                background: #e2e8f0;
                color: #64748b;
                font-size: 11px;
                font-weight: 600;
                border-radius: 4px;
                cursor: pointer;
                z-index: 1000;
                box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
                transition: all 0.15s ease;
                user-select: none;
                pointer-events: auto;
                opacity: 0;
                transform: scale(0.9);
            }
            .continue-writing-icon.visible {
                opacity: 1;
                transform: scale(1);
            }
            .continue-writing-icon:hover {
                background: #cbd5e1;
                box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
                transform: scale(1.05);
            }
            .continue-writing-icon:active {
                transform: scale(0.95);
            }
            .continue-writing-icon.loading {
                pointer-events: none;
                background: #f1f5f9;
            }
            .continue-writing-icon.loading::after {
                content: '';
                width: 10px;
                height: 10px;
                border: 2px solid rgba(100, 116, 139, 0.3);
                border-top-color: #64748b;
                border-radius: 50%;
                animation: continue-writing-spin 0.6s linear infinite;
            }
            .continue-writing-icon.loading span {
                display: none;
            }
            @keyframes continue-writing-spin {
                to { transform: rotate(360deg); }
            }
            /* 续写预览文本 - 浮动浅灰色，模拟无缝插入 */
            .continue-writing-preview-text {
                position: absolute;
                color: #9ca3af;
                white-space: pre-wrap;
                word-wrap: break-word;
                overflow-wrap: break-word;
                pointer-events: none;
                z-index: 998;
            }
            /* 续写预览时行的 margin 过渡效果 */
            .cm-line.continue-writing-spaced,
            .cm-gutterElement.continue-writing-spaced {
                transition: margin-bottom 0.15s ease-out;
            }
            /* 续写预览确认按钮 */
            .continue-writing-confirm-buttons {
                position: absolute;
                display: inline-flex;
                align-items: center;
                gap: 4px;
                z-index: 1001;
                background: white;
                padding: 2px 4px;
                border-radius: 4px;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
                border: 1px solid #e2e8f0;
            }
            .continue-writing-confirm-btn,
            .continue-writing-cancel-btn {
                display: flex;
                align-items: center;
                justify-content: center;
                width: 20px;
                height: 20px;
                border: none;
                border-radius: 3px;
                cursor: pointer;
                font-size: 14px;
                transition: all 0.15s ease;
            }
            .continue-writing-confirm-btn {
                background: #dcfce7;
                color: #16a34a;
            }
            .continue-writing-confirm-btn:hover {
                background: #bbf7d0;
            }
            .continue-writing-cancel-btn {
                background: #fee2e2;
                color: #dc2626;
            }
            .continue-writing-cancel-btn:hover {
                background: #fecaca;
            }
        `;
        document.head.appendChild(style);
    }

    // 续写图标元素
    let continueWritingIcon = null;
    // 当前光标所在行
    let currentCursorLine = -1;
    // 续写功能是否为自动触发模式 (true=自动, false=手动)
    let continueWritingAutoMode = false;
    // 续写功能是否启用（图标和Tab键）- 始终启用
    let continueWritingEnabled = true;
    // 隐藏图标的定时器
    let hideIconTimer = null;
    // 续写预览状态
    let continueWritingPreview = null;  // { cursorPos: number, text: string, lineNumber: number }
    // 确认按钮元素
    let confirmButtonsEl = null;
    // 预览浮动文本元素
    let previewTextEl = null;
    // 被添加了 margin 的行元素
    let spacedLineEl = null;
    // 被添加了 margin 的 gutter 元素
    let spacedGutterEl = null;
    // 原始的 margin-bottom 值
    let originalMarginBottom = '';
    // 原始的 gutter margin-bottom 值
    let originalGutterMarginBottom = '';
    // 需要维持的额外空间高度
    let requiredExtraSpace = 0;
    // 维护 margin 的定时器
    let marginMaintenanceTimer = null;
    // 自动触发定时器
    let autoTriggerTimer = null;
    // 自动触发间隔（毫秒）
    const AUTO_TRIGGER_INTERVAL = 1000;
    // 上次用户输入/删除的时间
    let lastUserInputTime = 0;
    // 自动触发需要的静默时间（毫秒）
    const AUTO_TRIGGER_IDLE_TIME = 2000;

    /**
     * 创建续写图标
     */
    function createContinueWritingIcon() {
        if (continueWritingIcon) return continueWritingIcon;

        injectContinueWritingStyles();

        continueWritingIcon = document.createElement('div');
        continueWritingIcon.className = 'continue-writing-icon';
        continueWritingIcon.title = '点击自动续写';
        continueWritingIcon.innerHTML = '<span>续</span>';

        // 点击触发续写
        continueWritingIcon.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            triggerContinueWriting();
        });

        // 将图标添加到编辑器容器
        const cmEditor = document.querySelector('.cm-editor');
        if (cmEditor) {
            // 确保编辑器有 position: relative
            if (getComputedStyle(cmEditor).position === 'static') {
                cmEditor.style.position = 'relative';
            }
            cmEditor.appendChild(continueWritingIcon);
        } else {
            document.body.appendChild(continueWritingIcon);
        }

        return continueWritingIcon;
    }

    /**
     * 更新续写图标的位置（放在当前行的末尾）
     */
    function updateContinueWritingIconPosition() {
        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) {
                hideContinueWritingIcon();
                return;
            }

            const state = view.state;
            const selection = state.selection.main;

            // 只在没有选中文本时显示图标（单纯光标）
            if (selection.from !== selection.to) {
                hideContinueWritingIcon();
                return;
            }

            const cursorPos = selection.head;
            const line = state.doc.lineAt(cursorPos);
            const lineNumber = line.number;

            // 检查当前行是否有内容（空行不显示图标）
            if (line.text.trim().length === 0) {
                hideContinueWritingIcon();
                return;
            }

            currentCursorLine = lineNumber;

            // 创建图标（如果不存在）
            if (!continueWritingIcon) {
                createContinueWritingIcon();
            }

            // 获取行末尾的坐标
            const lineEndPos = line.to;
            const coords = view.coordsAtPos(lineEndPos);

            if (!coords) {
                hideContinueWritingIcon();
                return;
            }

            // 获取编辑器容器的位置
            const cmEditor = document.querySelector('.cm-editor');
            const cmScroller = document.querySelector('.cm-scroller');
            if (!cmEditor || !cmScroller) {
                hideContinueWritingIcon();
                return;
            }

            const scrollerRect = cmScroller.getBoundingClientRect();

            // 检查行是否在可视区域内
            if (coords.top < scrollerRect.top || coords.bottom > scrollerRect.bottom) {
                hideContinueWritingIcon();
                return;
            }

            const editorRect = cmEditor.getBoundingClientRect();
            const lineHeight = coords.bottom - coords.top;

            // 计算图标位置（相对于编辑器）
            const iconLeft = coords.right - editorRect.left + 24;  // 行末尾右边 24px
            let iconTop = coords.top - editorRect.top + lineHeight / 2 - 9;  // 垂直居中

            // 确保图标不超出编辑器右边界
            const maxLeft = editorRect.width - 30;
            let finalLeft = iconLeft;

            // 如果图标会超出右边界，移到下一行的开头
            if (iconLeft > maxLeft) {
                // 获取内容区域的左边界
                const cmContent = document.querySelector('.cm-content');
                if (cmContent) {
                    const contentRect = cmContent.getBoundingClientRect();
                    finalLeft = contentRect.left - editorRect.left;  // 内容区左边界
                } else {
                    finalLeft = 50;  // 默认值
                }
                iconTop += lineHeight;  // 移到下一行
            }

            continueWritingIcon.style.left = `${finalLeft}px`;
            continueWritingIcon.style.top = `${iconTop}px`;

            // 显示图标
            showContinueWritingIcon();

        } catch (err) {
            console.error('[Overleaf Reader Injected] Error updating continue writing icon:', err);
            hideContinueWritingIcon();
        }
    }

    /**
     * 显示续写图标
     */
    function showContinueWritingIcon() {
        // 如果正在显示预览，不显示图标
        if (continueWritingPreview) {
            return;
        }

        if (continueWritingIcon) {
            // 清除隐藏定时器
            if (hideIconTimer) {
                clearTimeout(hideIconTimer);
                hideIconTimer = null;
            }
            continueWritingIcon.classList.add('visible');
        }
    }

    /**
     * 隐藏续写图标
     */
    function hideContinueWritingIcon() {
        if (continueWritingIcon) {
            continueWritingIcon.classList.remove('visible');
        }
    }

    /**
     * 获取当前行末尾之前的所有内容（无论光标在行的哪个位置）
     */
    function getContentBeforeCursor() {
        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) return '';

            const state = view.state;
            const selection = state.selection.main;
            const cursorPos = selection.head;

            // 获取当前行，使用行末尾位置
            const line = state.doc.lineAt(cursorPos);
            const lineEndPos = line.to;

            // 获取行末尾之前的内容，最多 2000 个字符
            const maxChars = 2000;
            const startPos = Math.max(0, lineEndPos - maxChars);
            return state.sliceDoc(startPos, lineEndPos);
        } catch (err) {
            console.error('[Overleaf Reader Injected] Error getting content before cursor:', err);
            return '';
        }
    }

    /**
     * 显示预览浮动文本（不实际插入到文档）
     * 模拟无缝插入效果：第一行从行末尾开始，换行后从编辑器左边开始
     * 同时添加占位元素撑开空间，避免和下方内容重叠
     * 注意：无论光标在行的哪个位置，都使用行末尾作为插入点
     */
    function showPreviewText(text) {
        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) return null;

            const state = view.state;
            const selection = state.selection.main;
            const cursorPos = selection.head;
            const line = state.doc.lineAt(cursorPos);
            const lineNumber = line.number;
            // 使用行末尾位置作为插入点
            const lineEndPos = line.to;

            // 移除已有的预览元素
            removePreviewText();

            const cmEditor = document.querySelector('.cm-editor');
            const cmContent = document.querySelector('.cm-content');
            if (!cmEditor || !cmContent) return null;

            // 获取行末尾位置坐标（而不是光标位置）
            const coords = view.coordsAtPos(lineEndPos);
            if (!coords) return null;

            const editorRect = cmEditor.getBoundingClientRect();
            const contentRect = cmContent.getBoundingClientRect();

            // 计算内容区域的左边界（相对于编辑器）
            const contentLeft = contentRect.left - editorRect.left;
            // 计算内容区域的宽度
            const contentWidth = contentRect.width;
            // 计算行末尾相对于内容区左边界的偏移（用于第一行缩进）
            const firstLineIndent = coords.right - contentRect.left;

            // 创建浮动预览文本元素
            previewTextEl = document.createElement('div');
            previewTextEl.className = 'continue-writing-preview-text';
            previewTextEl.textContent = text;

            // 获取编辑器的字体样式和行高
            let lineHeight = 20;  // 默认行高
            if (cmContent) {
                const computedStyle = getComputedStyle(cmContent);
                previewTextEl.style.fontFamily = computedStyle.fontFamily;
                previewTextEl.style.fontSize = computedStyle.fontSize;
                previewTextEl.style.lineHeight = computedStyle.lineHeight;
                lineHeight = parseFloat(computedStyle.lineHeight) || 20;
            }

            // 定位从内容区域左边开始
            previewTextEl.style.left = `${contentLeft}px`;
            previewTextEl.style.top = `${coords.top - editorRect.top}px`;
            // 设置宽度为内容区域宽度
            previewTextEl.style.width = `${contentWidth}px`;
            // 第一行使用 text-indent 缩进到行末尾位置
            previewTextEl.style.textIndent = `${firstLineIndent}px`;

            cmEditor.appendChild(previewTextEl);

            // 使用 requestAnimationFrame 确保渲染完成后再计算高度
            // 双重 rAF 确保浏览器完成布局计算
            requestAnimationFrame(() => {
                requestAnimationFrame(() => {
                    if (!previewTextEl) return;

                    const previewHeight = previewTextEl.offsetHeight;
                    // 需要额外撑开的空间 = 预览高度 - 一行的高度（第一行和当前行共用）
                    requiredExtraSpace = Math.max(0, previewHeight - lineHeight);

                    if (requiredExtraSpace > 0) {
                        // 启动 margin 维护定时器（使用行末尾位置）
                        startMarginMaintenance(lineEndPos);
                    }
                });
            });

            // 存储行末尾位置作为插入位置（cursorPos 字段实际存储的是 lineEndPos）
            return { cursorPos: lineEndPos, text, contentLeft, firstLineIndent, lineNumber };
        } catch (err) {
            console.error('[Overleaf Reader Injected] Error showing preview text:', err);
            return null;
        }
    }

    /**
     * 更新预览文本位置（跟随滚动）
     */
    function updatePreviewTextPosition() {
        if (!previewTextEl || !continueWritingPreview) return;

        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) return;

            const { cursorPos } = continueWritingPreview;
            const coords = view.coordsAtPos(cursorPos);
            if (!coords) {
                // 如果光标位置不在可视区域，隐藏预览
                previewTextEl.style.display = 'none';
                if (confirmButtonsEl) confirmButtonsEl.style.display = 'none';
                return;
            }

            const cmEditor = document.querySelector('.cm-editor');
            const cmScroller = document.querySelector('.cm-scroller');
            const cmContent = document.querySelector('.cm-content');
            if (!cmEditor || !cmScroller || !cmContent) return;

            const scrollerRect = cmScroller.getBoundingClientRect();

            // 检查是否在可视区域内
            if (coords.top < scrollerRect.top || coords.bottom > scrollerRect.bottom) {
                previewTextEl.style.display = 'none';
                if (confirmButtonsEl) confirmButtonsEl.style.display = 'none';
                return;
            }

            previewTextEl.style.display = '';
            if (confirmButtonsEl) confirmButtonsEl.style.display = '';

            const editorRect = cmEditor.getBoundingClientRect();
            const contentRect = cmContent.getBoundingClientRect();

            // 重新计算内容区域位置和缩进
            const contentLeft = contentRect.left - editorRect.left;
            const contentWidth = contentRect.width;
            const firstLineIndent = coords.right - contentRect.left;

            // 更新位置
            previewTextEl.style.left = `${contentLeft}px`;
            previewTextEl.style.top = `${coords.top - editorRect.top}px`;
            previewTextEl.style.width = `${contentWidth}px`;
            previewTextEl.style.textIndent = `${firstLineIndent}px`;

            // 同时更新确认按钮位置（在预览文本的最后一行末尾）
            if (confirmButtonsEl) {
                const previewRect = previewTextEl.getBoundingClientRect();
                // 按钮放在预览文本框的右下角
                const btnLeft = previewRect.right - editorRect.left + 4;
                const btnTop = previewRect.bottom - editorRect.top - 24;
                confirmButtonsEl.style.left = `${Math.min(btnLeft, editorRect.width - 60)}px`;
                confirmButtonsEl.style.top = `${btnTop}px`;
            }

        } catch (err) {
            console.error('[Overleaf Reader Injected] Error updating preview text position:', err);
        }
    }

    /**
     * 移除预览浮动文本并恢复行高
     */
    function removePreviewText() {
        // 停止 margin 维护
        stopMarginMaintenance();

        if (previewTextEl) {
            previewTextEl.remove();
            previewTextEl = null;
        }
        // 恢复原始 margin-bottom 并移除 transition class
        if (spacedLineEl) {
            spacedLineEl.classList.remove('continue-writing-spaced');
            spacedLineEl.style.marginBottom = originalMarginBottom;
            spacedLineEl = null;
            originalMarginBottom = '';
        }
        // 恢复 gutter 的原始 margin-bottom 并移除 transition class
        if (spacedGutterEl) {
            spacedGutterEl.classList.remove('continue-writing-spaced');
            spacedGutterEl.style.marginBottom = originalGutterMarginBottom;
            spacedGutterEl = null;
            originalGutterMarginBottom = '';
        }
        requiredExtraSpace = 0;
    }

    /**
     * 启动 margin 维护定时器
     * 持续检查并重新应用 margin，防止被 CodeMirror 重置
     */
    function startMarginMaintenance(cursorPos) {
        stopMarginMaintenance();

        const applyMargin = () => {
            if (!continueWritingPreview || requiredExtraSpace <= 0) {
                stopMarginMaintenance();
                return;
            }

            try {
                const view = window.overleaf?.unstable?.store?.get('editor.view');
                if (!view) return;

                // 找到当前行的 DOM 元素
                const domAtPos = view.domAtPos(cursorPos);
                let currentLineEl = domAtPos.node;
                // 向上查找 .cm-line 元素
                while (currentLineEl && !currentLineEl.classList?.contains('cm-line')) {
                    currentLineEl = currentLineEl.parentElement;
                }

                if (currentLineEl) {
                    // 检查并应用 margin
                    const currentMargin = parseFloat(currentLineEl.style.marginBottom) || 0;
                    if (currentMargin < requiredExtraSpace) {
                        if (spacedLineEl !== currentLineEl) {
                            // 恢复旧行的 margin 和 class
                            if (spacedLineEl) {
                                spacedLineEl.style.marginBottom = originalMarginBottom;
                                spacedLineEl.classList.remove('continue-writing-spaced');
                            }
                            originalMarginBottom = currentLineEl.style.marginBottom;
                            spacedLineEl = currentLineEl;
                            // 添加 class 启用 transition
                            currentLineEl.classList.add('continue-writing-spaced');
                        }
                        currentLineEl.style.marginBottom = `${requiredExtraSpace}px`;
                    }
                }

                // 同时处理 gutter 行号元素
                if (continueWritingPreview && continueWritingPreview.lineNumber) {
                    const lineNumber = continueWritingPreview.lineNumber;
                    // 查找对应行号的 gutter 元素
                    const gutterElements = document.querySelectorAll('.cm-lineNumbers .cm-gutterElement');
                    for (const gutterEl of gutterElements) {
                        // gutter 元素的文本内容是行号
                        if (gutterEl.textContent.trim() === String(lineNumber)) {
                            const currentGutterMargin = parseFloat(gutterEl.style.marginBottom) || 0;
                            if (currentGutterMargin < requiredExtraSpace) {
                                if (spacedGutterEl !== gutterEl) {
                                    // 恢复旧 gutter 的 margin 和 class
                                    if (spacedGutterEl) {
                                        spacedGutterEl.style.marginBottom = originalGutterMarginBottom;
                                        spacedGutterEl.classList.remove('continue-writing-spaced');
                                    }
                                    originalGutterMarginBottom = gutterEl.style.marginBottom;
                                    spacedGutterEl = gutterEl;
                                    // 添加 class 启用 transition
                                    gutterEl.classList.add('continue-writing-spaced');
                                }
                                gutterEl.style.marginBottom = `${requiredExtraSpace}px`;
                            }
                            break;
                        }
                    }
                }
            } catch (err) {
                // 忽略错误
            }
        };

        // 立即应用一次
        applyMargin();

        // 每 50ms 检查一次
        marginMaintenanceTimer = setInterval(applyMargin, 50);
    }

    /**
     * 停止 margin 维护定时器
     */
    function stopMarginMaintenance() {
        if (marginMaintenanceTimer) {
            clearInterval(marginMaintenanceTimer);
            marginMaintenanceTimer = null;
        }
    }

    /**
     * 取消预览（只移除浮动文本，不影响文档）
     */
    function cancelPreview() {
        if (!continueWritingPreview) return false;

        try {
            // 只移除浮动预览文本
            removePreviewText();
            continueWritingPreview = null;
            console.log('[Overleaf Reader Injected] Preview cancelled');
            return true;
        } catch (err) {
            console.error('[Overleaf Reader Injected] Error cancelling preview:', err);
            return false;
        }
    }

    /**
     * 确认预览内容（插入文本到文档）
     */
    function confirmPreviewContent() {
        if (!continueWritingPreview) return false;

        try {
            const view = window.overleaf?.unstable?.store?.get('editor.view');
            if (!view || !view.state) return false;

            const { cursorPos, text } = continueWritingPreview;

            // 实际插入内容到文档
            view.dispatch({
                changes: { from: cursorPos, to: cursorPos, insert: text },
                selection: { anchor: cursorPos + text.length }
            });

            view.focus();

            // 移除浮动预览文本
            removePreviewText();
            continueWritingPreview = null;
            console.log('[Overleaf Reader Injected] Preview confirmed and text inserted');
            return true;
        } catch (err) {
            console.error('[Overleaf Reader Injected] Error confirming preview:', err);
            return false;
        }
    }

    /**
     * 显示确认按钮（在预览文本末尾）
     */
    function showConfirmButtons() {
        if (confirmButtonsEl) {
            hideConfirmButtons();
        }

        try {
            if (!continueWritingPreview || !previewTextEl) return;

            const cmEditor = document.querySelector('.cm-editor');
            if (!cmEditor) return;

            const editorRect = cmEditor.getBoundingClientRect();
            const previewRect = previewTextEl.getBoundingClientRect();

            // 创建确认按钮容器
            confirmButtonsEl = document.createElement('div');
            confirmButtonsEl.className = 'continue-writing-confirm-buttons';

            // 确认按钮
            const confirmBtn = document.createElement('button');
            confirmBtn.className = 'continue-writing-confirm-btn';
            confirmBtn.innerHTML = '✓';
            confirmBtn.title = '确认插入';
            confirmBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                confirmPreviewContent();
                hideConfirmButtons();
                // 重新显示续写图标
                updateContinueWritingIconPosition();
            });

            // 取消按钮
            const cancelBtn = document.createElement('button');
            cancelBtn.className = 'continue-writing-cancel-btn';
            cancelBtn.innerHTML = '✕';
            cancelBtn.title = '取消';
            cancelBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                cancelPreview();
                hideConfirmButtons();
                // 重新显示续写图标
                updateContinueWritingIconPosition();
            });

            confirmButtonsEl.appendChild(confirmBtn);
            confirmButtonsEl.appendChild(cancelBtn);

            // 定位到预览文本的右下角（最后一行末尾）
            const left = previewRect.right - editorRect.left + 4;
            const top = previewRect.bottom - editorRect.top - 24;

            confirmButtonsEl.style.left = `${Math.min(left, editorRect.width - 60)}px`;
            confirmButtonsEl.style.top = `${top}px`;

            cmEditor.appendChild(confirmButtonsEl);

        } catch (err) {
            console.error('[Overleaf Reader Injected] Error showing confirm buttons:', err);
        }
    }

    /**
     * 隐藏确认按钮
     */
    function hideConfirmButtons() {
        if (confirmButtonsEl) {
            confirmButtonsEl.remove();
            confirmButtonsEl = null;
        }
    }

    /**
     * 触发续写功能
     */
    function triggerContinueWriting() {
        if (!continueWritingIcon) return;

        // 设置加载状态
        continueWritingIcon.classList.add('loading');

        const contentBeforeCursor = getContentBeforeCursor();

        if (!contentBeforeCursor || contentBeforeCursor.trim().length < 50) {
            console.log('[Overleaf Reader Injected] Content too short for continue writing');
            continueWritingIcon.classList.remove('loading');
            return;
        }

        console.log('[Overleaf Reader Injected] Triggering continue writing, content length:', contentBeforeCursor.length);

        // 发送消息给 content script
        window.postMessage({
            type: 'OVERLEAF_CONTINUE_WRITING',
            contentBeforeCursor: contentBeforeCursor
        }, '*');
    }

    /**
     * 处理续写结果
     */
    window.addEventListener('message', function(event) {
        if (event.data && event.data.type === 'OVERLEAF_CONTINUE_WRITING_RESULT') {
            console.log('[Overleaf Reader Injected] Received continue writing result:', event.data);

            // 移除加载状态
            if (continueWritingIcon) {
                continueWritingIcon.classList.remove('loading');
            }

            if (event.data.success && event.data.continuation) {
                // 如果已有预览，先清除
                if (continueWritingPreview) {
                    cancelPreview();
                    hideConfirmButtons();
                }

                // 隐藏续写图标
                hideContinueWritingIcon();

                // 显示预览浮动文本（不实际插入）
                continueWritingPreview = showPreviewText(event.data.continuation);

                if (continueWritingPreview) {
                    // 显示确认/取消按钮
                    setTimeout(() => {
                        showConfirmButtons();
                        // 确保编辑器保持焦点，用户可以继续输入
                        const view = window.overleaf?.unstable?.store?.get('editor.view');
                        if (view) view.focus();
                    }, 50);
                    console.log('[Overleaf Reader Injected] Continuation preview shown, waiting for confirmation');
                }
            } else {
                console.error('[Overleaf Reader Injected] Continue writing failed:', event.data.error);
                // 显示错误提示给用户
                showContinueWritingError('续写失败: ' + (event.data.error || '未知错误') + AI_MODEL_ERROR_HINT_CONTINUE);
            }
        }

        // 监听续写触发模式变化 (手动/自动)
        if (event.data && event.data.type === 'OVERLEAF_CONTINUE_WRITING_ENABLED_CHANGED') {
            continueWritingAutoMode = event.data.enabled;
            console.log('[Overleaf Reader Injected] Continue writing auto mode changed:', continueWritingAutoMode);

            // 根据模式启动或停止自动触发
            if (continueWritingAutoMode) {
                startAutoTrigger();
            } else {
                stopAutoTrigger();
            }

            // 图标始终显示（两种模式都可用）
            updateContinueWritingIconPosition();
        }
    });

    /**
     * 启动自动触发定时器
     */
    function startAutoTrigger() {
        stopAutoTrigger();

        autoTriggerTimer = setInterval(() => {
            // 如果已有预览正在等待确认，跳过
            if (continueWritingPreview) {
                return;
            }

            // 如果正在加载中，跳过
            if (continueWritingIcon && continueWritingIcon.classList.contains('loading')) {
                return;
            }

            // 检查用户是否在过去2秒内有输入/删除操作
            const timeSinceLastInput = Date.now() - lastUserInputTime;
            if (timeSinceLastInput < AUTO_TRIGGER_IDLE_TIME) {
                return;
            }

            try {
                const view = window.overleaf?.unstable?.store?.get('editor.view');
                if (!view || !view.state) return;

                const state = view.state;
                const selection = state.selection.main;

                // 只在没有选中文本时处理
                if (selection.from !== selection.to) return;

                const cursorPos = selection.head;
                const line = state.doc.lineAt(cursorPos);

                // 检查当前行是否有内容
                if (line.text.trim().length > 0) {
                    console.log('[Overleaf Reader Injected] Auto-triggering continue writing');
                    triggerContinueWriting();
                }
            } catch (err) {
                console.error('[Overleaf Reader Injected] Error in auto-trigger:', err);
            }
        }, AUTO_TRIGGER_INTERVAL);

        console.log('[Overleaf Reader Injected] Auto-trigger started');
    }

    /**
     * 停止自动触发定时器
     */
    function stopAutoTrigger() {
        if (autoTriggerTimer) {
            clearInterval(autoTriggerTimer);
            autoTriggerTimer = null;
            console.log('[Overleaf Reader Injected] Auto-trigger stopped');
        }
    }

    /**
     * 设置续写图标的监听器
     */
    function setupContinueWritingIcon() {
        // 使用 UNSTABLE_editor:extensions 监听光标变化
        if (window.overleaf && window.overleaf.unstable && window.overleaf.unstable.onContentChange) {
            // 已经有监听器了，只需要在光标变化时更新图标位置
        }

        // 监听滚动事件以更新图标和预览文本位置
        const cmScroller = document.querySelector('.cm-scroller');
        if (cmScroller) {
            cmScroller.addEventListener('scroll', function() {
                // 实时更新预览文本位置
                if (previewTextEl && continueWritingPreview) {
                    updatePreviewTextPosition();
                }

                // 滚动时延迟更新图标位置
                if (hideIconTimer) clearTimeout(hideIconTimer);
                hideIconTimer = setTimeout(() => {
                    updateContinueWritingIconPosition();
                }, 100);
            });
        }

        // 监听编辑器输入事件，用户输入时取消预览
        const cmContent = document.querySelector('.cm-content');
        if (cmContent) {
            cmContent.addEventListener('input', function() {
                // 记录用户输入时间
                lastUserInputTime = Date.now();

                // 如果有预览正在显示，用户输入时取消它
                if (continueWritingPreview) {
                    cancelPreview();
                    hideConfirmButtons();
                    // 重新显示续写图标
                    updateContinueWritingIconPosition();
                }
            });

            // 监听删除键，删除内容时也取消预览
            cmContent.addEventListener('keydown', function(e) {
                if (e.key === 'Backspace' || e.key === 'Delete') {
                    // 记录用户删除时间
                    lastUserInputTime = Date.now();

                    if (continueWritingPreview) {
                        cancelPreview();
                        hideConfirmButtons();
                        // 重新显示续写图标
                        updateContinueWritingIconPosition();
                    }
                }
            });
        }

        // 监听 Tab 键
        document.addEventListener('keydown', function(e) {
            if (e.key !== 'Tab') return;

            // 情况1：有预览等待确认时，Tab 等同于确认
            if (continueWritingPreview) {
                e.preventDefault();
                e.stopPropagation();
                confirmPreviewContent();
                hideConfirmButtons();
                updateContinueWritingIconPosition();
                return;
            }

            // 情况2：光标在行末尾时，Tab 触发续写
            try {
                const view = window.overleaf?.unstable?.store?.get('editor.view');
                if (!view || !view.state) return;

                const state = view.state;
                const selection = state.selection.main;

                // 只在没有选中文本时处理
                if (selection.from !== selection.to) return;

                const cursorPos = selection.head;
                const line = state.doc.lineAt(cursorPos);

                // 检查光标是否在行末尾
                if (cursorPos === line.to && line.text.trim().length > 0) {
                    e.preventDefault();
                    e.stopPropagation();
                    triggerContinueWriting();
                }
            } catch (err) {
                console.error('[Overleaf Reader Injected] Error handling Tab key:', err);
            }
        }, true);  // 使用捕获阶段

        // 监听 mousedown 事件，处理点击时的位置补偿
        // 如果点击在预览行下方，需要将坐标减去额外的 margin 来计算正确位置
        document.addEventListener('mousedown', function(e) {
            if (!continueWritingPreview) return;
            if (requiredExtraSpace <= 0) return;

            // 排除点击确认/取消按钮和预览文本
            if (e.target.closest('.continue-writing-confirm-buttons')) return;
            if (e.target.closest('.continue-writing-preview-text')) return;

            // 检查是否点击在编辑器内容区域
            const cmEditor = document.querySelector('.cm-editor');
            const cmContent = document.querySelector('.cm-content');
            if (!cmEditor || !cmContent) return;
            if (!cmContent.contains(e.target) && !e.target.closest('.cm-content')) return;

            if (!spacedLineEl) return;

            const lineRect = spacedLineEl.getBoundingClientRect();
            const lineBottom = lineRect.bottom;
            const clickY = e.clientY;

            // 如果点击位置在预览行下方（受额外 margin 影响的区域）
            if (clickY > lineBottom) {
                // 阻止原始事件，我们手动处理
                e.preventDefault();
                e.stopPropagation();

                // 保存点击坐标和调整量
                const savedX = e.clientX;
                const savedExtraSpace = requiredExtraSpace;

                // 先取消预览（恢复行高）
                cancelPreview();
                hideConfirmButtons();

                // 等待布局更新后，再用调整后的坐标计算位置
                requestAnimationFrame(() => {
                    try {
                        const view = window.overleaf?.unstable?.store?.get('editor.view');
                        if (!view) return;

                        // 计算调整后的 Y 坐标（减去额外的 margin）
                        // 因为布局已恢复，下面的内容往上移动了 savedExtraSpace
                        const adjustedY = clickY - savedExtraSpace;

                        // 使用调整后的坐标获取正确的文档位置
                        const pos = view.posAtCoords({ x: savedX, y: adjustedY });

                        // 设置光标到计算出的正确位置
                        if (pos !== null) {
                            view.dispatch({
                                selection: { anchor: pos }
                            });
                        }
                        view.focus();

                        updateContinueWritingIconPosition();
                    } catch (err) {
                        console.error('[Overleaf Reader Injected] Error handling click position:', err);
                    }
                });
            }
            // 如果点击在预览行或上方，不需要补偿，让原始事件正常处理
        }, true);  // 使用捕获阶段，在 CodeMirror 处理之前执行

        // 定期更新图标位置（作为 fallback）并检查光标是否移动到其他行
        setInterval(() => {
            updateContinueWritingIconPosition();

            // 检查光标是否移动到其他行，如果是则取消预览
            if (continueWritingPreview) {
                try {
                    const view = window.overleaf?.unstable?.store?.get('editor.view');
                    if (view && view.state) {
                        const state = view.state;
                        const selection = state.selection.main;
                        const cursorPos = selection.head;
                        const currentLine = state.doc.lineAt(cursorPos);

                        if (currentLine.number !== continueWritingPreview.lineNumber) {
                            cancelPreview();
                            hideConfirmButtons();
                            updateContinueWritingIconPosition();
                        }
                    }
                } catch (err) {
                    // 忽略错误
                }
            }
        }, 500);

        // 请求当前续写开关状态
        window.postMessage({
            type: 'OVERLEAF_GET_CONTINUE_WRITING_ENABLED'
        }, '*');

        console.log('[Overleaf Reader Injected] Continue writing icon setup complete');
    }

    // 延迟初始化续写图标
    setTimeout(setupContinueWritingIcon, 2000);

})();