// js/sub_block_segmenter.js
(function SubBlockSegmenter(global) {
    /**
     * 将块级元素内容按标点分割成子块 (span.sub-block)。
     * @param {HTMLElement} blockElement - 要分割的块级元素 (如 p, h1-h6)。
     * @param {string|number} parentBlockIndex - 父块的索引。
     */
    function segmentBlockIntoSubBlocks(blockElement, parentBlockIndex, force = false) {
        // 性能埋点：分块开始
        performance.mark('subBlock-start');
        // 调试开关：本文件的检测/一致性类日志统一受控
        const __SUBBLOCK_DEBUG__ = (function(){
            try {
                return !!(window && (window.ENABLE_SUBBLOCK_DEBUG || localStorage.getItem('ENABLE_SUBBLOCK_DEBUG') === 'true'));
            } catch { return false; }
        })();

        // ===== 新增：分割前检测 =====
        const preSubBlocks = Array.from(blockElement.querySelectorAll('.sub-block'));
        if (__SUBBLOCK_DEBUG__ && preSubBlocks.length > 0) {
            console.warn(`[SubBlockSegmenter][检测] 分割前已存在 ${preSubBlocks.length} 个 .sub-block，内容摘要：`, preSubBlocks.map(sb => (sb.textContent || '').substring(0, 30)));
        }
        const preTextContent = blockElement.textContent;

        // ===== 新增：详细日志 =====
        // console.log(`[SubBlockSegmenter] 开始分块 #${parentBlockIndex}, 元素类型: ${blockElement.tagName}, 内容前20字符: "${(blockElement.textContent || '').substring(0, 20)}..."`);

        // 检查是否已经有子块，如果有则记录它们
        const existingSubBlocks = blockElement.querySelectorAll('.sub-block');
        if (existingSubBlocks.length > 0) {
            // console.log(`[SubBlockSegmenter] 警告: 块 #${parentBlockIndex} 已有 ${existingSubBlocks.length} 个子块，这些将被重新生成`);
            // console.log(`[SubBlockSegmenter] 现有子块ID列表:`, Array.from(existingSubBlocks).map(sb => sb.dataset.subBlockId));
        }

        // 优化：只有当文本足够长且包含中文或英文句读符号才进行分块
        const rawText = (blockElement.textContent || '').trim();
        const containsCnPeriod = rawText.indexOf('。') !== -1;
        const containsEnPunct = /[\.!?;:]/.test(rawText);
        // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 文本长度: ${rawText.length}, CN句号: ${containsCnPeriod}, EN标点: ${containsEnPunct}`);

        // ===== 新增：公式感知检测 =====
        const hasFormula = checkForFormulas(blockElement, rawText);
        if (__SUBBLOCK_DEBUG__ && hasFormula) {
            console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 包含数学公式，启用公式感知分割`);
        }

        // 修改分割条件：包含公式的块使用不同的分割策略
        // 仅当文本很短且也不含中英文句读时才跳过；
        // 只要存在句读符，即使很短也执行分块以支持精确高亮。
        if (!force && !hasFormula && (rawText.length < 80 && (!containsCnPeriod && !containsEnPunct))) {
            // 跳过分割
            // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 不满足分块条件，跳过分块`);
            performance.mark('subBlock-end');
            performance.measure('subBlockSegmentSkipping', 'subBlock-start', 'subBlock-end');
            return;
        }

        // 如果块元素本身是表格，或者其内部有表格，则不进行分割处理
        if (blockElement.tagName === 'TABLE' || blockElement.querySelector('table')) {
            // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 是表格或包含表格，跳过分块`);
            return; // 直接返回，不修改表格内容
        }

        // ===== 新增：检测 Markdown 表格语法 =====
        // 检测表格分隔符行：|---|---|... 或 |:---|---:| 等
        const hasMarkdownTableSeparator = /\|(:?-+:?\|)+/.test(rawText);
        if (hasMarkdownTableSeparator) {
            console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 包含 Markdown 表格语法，跳过分块以保持表格完整性`);
            return; // 直接返回，不分割 Markdown 表格
        }

        // ===== 新增：公式感知分割处理 =====
        if (hasFormula) {
            return segmentFormulaAwareBlock(blockElement, parentBlockIndex, rawText, __SUBBLOCK_DEBUG__);
        }

        // ===== 新增：保存原始内容，用于对比 =====
        const originalContent = blockElement.innerHTML;
        const originalTextContent = blockElement.textContent;

        let subBlockTrueCounter = 0; // Counter for non-empty sub-blocks
        const newChildNodesContainer = document.createDocumentFragment();
        let firstGeneratedSubBlockElement = null; // Store the first (potentially only) sub-block

        // Define delimiters: Chinese period or common English sentence punctuation
        // The regex captures the delimiter itself and any trailing whitespace.
        const delimiterRegex = /([。\.!?;:])(\s*)/g;

        let currentSpanContentNodes = []; // Nodes for the current sub-block being built

        function flushCurrentSpan(isEndOfBlock = false) {
            if (currentSpanContentNodes.length > 0) {
                const tempSpan = document.createElement('span'); // Temporary span to check if it's empty
                currentSpanContentNodes.forEach(n => tempSpan.appendChild(n.cloneNode(true))); // Use cloned nodes for check

                if (tempSpan.textContent.trim() !== "" || (isEndOfBlock && tempSpan.innerHTML.trim() !== "")) { // Ensure span is not just whitespace or empty HTML
                    const span = document.createElement('span');
                    span.className = 'sub-block';
                    const subBlockId = `${parentBlockIndex}.${subBlockTrueCounter}`;
                    span.dataset.subBlockId = subBlockId; // Corrected template literal

                    // ===== 新增：记录子块内容 =====
                    const subBlockContent = tempSpan.textContent;
                    // console.log(`[SubBlockSegmenter] 创建子块 #${subBlockId}, 内容前20字符: "${subBlockContent.substring(0, 20)}..."`);

                    currentSpanContentNodes.forEach(n => span.appendChild(n)); // Append original nodes
                    newChildNodesContainer.appendChild(span);

                    if (subBlockTrueCounter === 0) { // If this is the first non-empty sub-block
                        firstGeneratedSubBlockElement = span;
                    } else { // If we've already found one and now found another, it's not the only one
                        firstGeneratedSubBlockElement = null; // Invalidate, as there are multiple
                    }
                    subBlockTrueCounter++;
                } else {
                    // console.log(`[SubBlockSegmenter] 跳过空子块 #${parentBlockIndex}.${subBlockTrueCounter}`);
                }
                currentSpanContentNodes = [];
            }
        }

        function processNodesRecursive(nodes) {
            for (const node of nodes) {
                if (node.nodeType === Node.TEXT_NODE) {
                    let text = node.textContent;
                    let lastIndex = 0;
                    let match;
                    if (text.trim() === '' && currentSpanContentNodes.length === 0) { // Skip leading pure whitespace text nodes if current span is empty
                        continue;
                    }
                    while ((match = delimiterRegex.exec(text)) !== null) {
                        // Add text before delimiter
                        if (match.index > lastIndex) {
                            currentSpanContentNodes.push(document.createTextNode(text.substring(lastIndex, match.index)));
                        }
                        // Add the delimiter itself
                        currentSpanContentNodes.push(document.createTextNode(match[1]));
                        // Add trailing space if captured
                        if (match[2]) {
                            currentSpanContentNodes.push(document.createTextNode(match[2]));
                        }
                        flushCurrentSpan(); // End of a sub-block
                        lastIndex = match.index + match[0].length;
                    }
                    // Add remaining text after the last delimiter
                    if (lastIndex < text.length) {
                        currentSpanContentNodes.push(document.createTextNode(text.substring(lastIndex)));
                    }
                } else if (node.nodeType === Node.ELEMENT_NODE) {
                    // For inline elements, clone them and add to current span content.
                    currentSpanContentNodes.push(node.cloneNode(true));
                } else {
                    // Other node types (comments, etc.), clone and add.
                    currentSpanContentNodes.push(node.cloneNode(true));
                }
            }
        }

        processNodesRecursive(Array.from(blockElement.childNodes));
        flushCurrentSpan(true); // Flush any remaining content, isEndOfBlock = true

        // ===== 新增：对比分块前后的内容 =====
        // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 分块前文本长度: ${originalTextContent.length}`);

        // Clear original content and append new sub-block spans
        blockElement.innerHTML = '';
        blockElement.appendChild(newChildNodesContainer);

        // ===== 新增：分割后检测 =====
        const postSubBlocks = Array.from(blockElement.querySelectorAll('.sub-block'));
        const postTextContent = blockElement.textContent;
        if (preSubBlocks.length > 0) {
            if (__SUBBLOCK_DEBUG__ && postSubBlocks.length < preSubBlocks.length) {
                console.error(`[SubBlockSegmenter][检测] 分割后子块数量变少！分割前: ${preSubBlocks.length}，分割后: ${postSubBlocks.length}`);
                console.error(`[SubBlockSegmenter][检测] 分割前内容摘要:`, preSubBlocks.map(sb => (sb.textContent || '').substring(0, 30)));
                console.error(`[SubBlockSegmenter][检测] 分割后内容摘要:`, postSubBlocks.map(sb => (sb.textContent || '').substring(0, 30)));
            }
            // 检查内容拼接（如前后内容合并到一个 span）
            if (__SUBBLOCK_DEBUG__ && postSubBlocks.length === 1 && preSubBlocks.length > 1) {
                const mergedContent = postSubBlocks[0].textContent || '';
                const preConcat = preSubBlocks.map(sb => sb.textContent || '').join('');
                if (mergedContent.replace(/\s+/g, '') === preConcat.replace(/\s+/g, '')) {
                    console.error(`[SubBlockSegmenter][检测] 分割后所有内容被合并到一个子块！内容：${mergedContent.substring(0, 50)}...`);
                }
            }
        }
        if (postSubBlocks.length > 0) {
            // 检查是否有异常长的子块（仅在开启调试时输出）
            const maxLen = Math.max(...postSubBlocks.map(sb => (sb.textContent || '').length));
            if (__SUBBLOCK_DEBUG__ && maxLen > 500 && postSubBlocks.length > 1) {
                console.warn(`[SubBlockSegmenter][检测] 存在异常长的子块，长度: ${maxLen}`);
            }
        }

        // ===== 新增：验证分块后的内容完整性 =====
        const newTextContent = blockElement.textContent;
        // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 分块后文本长度: ${newTextContent.length}`);

        if (__SUBBLOCK_DEBUG__ && originalTextContent.trim() !== newTextContent.trim()) {
            console.warn(`[SubBlockSegmenter] 警告: 块 #${parentBlockIndex} 分块前后内容不一致!`);
            console.warn(`[SubBlockSegmenter] 分块前内容: "${originalTextContent.substring(0, 50)}..."`);
            console.warn(`[SubBlockSegmenter] 分块后内容: "${newTextContent.substring(0, 50)}..."`);
        }

        // After all processing, if firstGeneratedSubBlockElement is still set (i.e., subBlockTrueCounter ended at 1)
        if (firstGeneratedSubBlockElement && subBlockTrueCounter === 1) {
            firstGeneratedSubBlockElement.dataset.isOnlySubBlock = "true";
            // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 只有一个子块，标记为 isOnlySubBlock=true`);
        }

        // ===== 新增：记录最终生成的子块 =====
        const finalSubBlocks = blockElement.querySelectorAll('.sub-block');
        // console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 最终生成 ${finalSubBlocks.length} 个子块`);
        // console.log(`[SubBlockSegmenter] 子块ID列表:`, Array.from(finalSubBlocks).map(sb => sb.dataset.subBlockId));

        // 分割后检测分割一致性
        if (window.data && window.data.annotations) {
            const allSubBlocks = Array.from(blockElement.querySelectorAll('.sub-block'));
            allSubBlocks.forEach(sb => {
                const subBlockId = sb.dataset.subBlockId;
                const content = (sb.textContent || '').trim();
                // 查找 annotation 里的 exact
                const ann = window.data.annotations.find(a => a.target && a.target.selector && a.target.selector[0] && a.target.selector[0].subBlockId === subBlockId);
                if (__SUBBLOCK_DEBUG__ && ann && ann.target.selector[0].exact) {
                    const exact = ann.target.selector[0].exact.trim();
                    if (content !== exact) {
                        console.warn(`[分割一致性检测] subBlockId=${subBlockId} 分割内容与 annotation.exact 不一致！\n分割内容: "${content}"\nannotation.exact: "${exact}"`);
                    }
                }
                //console.log(`[分割一致性] subBlockId=${subBlockId} 内容: "${content.substring(0, 40)}..."`);
            });
        }

        // 性能埋点：分块结束
        performance.mark('subBlock-end');
        performance.measure('subBlockSegment', 'subBlock-start', 'subBlock-end');
    }

    // Expose public interface
    // ===== 新增：公式检测函数 =====
    function checkForFormulas(blockElement, rawText) {
        // 检查LaTeX公式模式
        const latexPatterns = [
            /\$\$[\s\S]*?\$\$/,     // 块级公式 $$...$$
            /\\\[[\s\S]*?\\\]/,   // 块级公式 \[...\]
            /\$[^$\n]+\$/,          // 行内公式 $...$
            /\\\([^\n]*?\\\)/     // 行内公式 \(...\)
        ];
        
        // 检查是否包含数学公式
        for (const pattern of latexPatterns) {
            if (pattern.test(rawText)) {
                return true;
            }
        }
        
        // 检查是否已经渲染的KaTeX元素
        if (blockElement.querySelector('.katex, .katex-display, .katex-inline')) {
            return true;
        }
        
        return false;
    }

    // ===== 新增：将整个块包装为单一子块（保留内部 DOM，不破坏 KaTeX） =====
    function wrapAsSingleSubBlock(blockElement, parentBlockIndex) {
        // 若已经是单一子块则跳过
        const existing = blockElement.querySelectorAll(':scope > .sub-block');
        if (existing.length === 1 && existing[0].dataset && existing[0].dataset.isOnlySubBlock === 'true') {
            return;
        }
        const span = document.createElement('span');
        span.className = 'sub-block';
        span.dataset.subBlockId = `${parentBlockIndex}.0`;
        span.dataset.isOnlySubBlock = 'true';
        while (blockElement.firstChild) {
            span.appendChild(blockElement.firstChild);
        }
        blockElement.appendChild(span);
    }

    // ===== 新增：公式感知的分割函数 =====
    function segmentFormulaAwareBlock(blockElement, parentBlockIndex, rawText, debug) {
        if (debug) {
            console.log(`[SubBlockSegmenter] 开始公式感知分割，块 #${parentBlockIndex}`);
        }

        // ===== 新增：检测 Markdown 表格语法 =====
        const hasMarkdownTableSeparator = /\|(:?-+:?\|)+/.test(rawText);
        if (hasMarkdownTableSeparator) {
            if (debug) {
                console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 含表格语法，包装为单一子块（原子）`);
            }
            wrapAsSingleSubBlock(blockElement, parentBlockIndex);
            return;
        }

        // 检测公式位置和类型
        const formulaInfo = analyzeFormulas(blockElement, rawText);

        // 为了避免切断 KaTeX 或将 $$...$$ 拆分为多个子块，
        // 对包含公式的块统一包装为一个原子子块。
        if (formulaInfo.hasBlockFormula || formulaInfo.renderedFormulas.length > 0) {
            if (debug) {
                console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 含块级/已渲染公式，包装为单一子块（原子）。`);
            }
            wrapAsSingleSubBlock(blockElement, parentBlockIndex);
            return;
        }

        if (formulaInfo.hasInlineFormula) {
            // 只有行内公式：使用保守分割策略，仅按句号分割且保留 DOM
            return segmentWithInlineFormulaProtection(blockElement, parentBlockIndex, debug);
        }

        // 没有检测到公式，交由普通分割逻辑（由调用方继续执行）
        return;
    }

    // ===== 新增：分析公式信息 =====
    function analyzeFormulas(blockElement, rawText) {
        const info = {
            hasBlockFormula: false,
            hasInlineFormula: false,
            blockFormulas: [],
            inlineFormulas: [],
            renderedFormulas: []
        };

        // 检测块级公式
        const blockFormulaRegex = /\$\$[\s\S]*?\$\$|\\\[[\s\S]*?\\\]/g;
        let match;
        while ((match = blockFormulaRegex.exec(rawText)) !== null) {
            info.hasBlockFormula = true;
            info.blockFormulas.push({
                content: match[0],
                start: match.index,
                end: match.index + match[0].length
            });
        }

        // 检测行内公式
        const inlineFormulaRegex = /\$[^$\n]+\$|\\\([^\n]*?\\\)/g;
        while ((match = inlineFormulaRegex.exec(rawText)) !== null) {
            info.hasInlineFormula = true;
            info.inlineFormulas.push({
                content: match[0],
                start: match.index,
                end: match.index + match[0].length
            });
        }

        // 检测已渲染的公式
        const katexElements = blockElement.querySelectorAll('.katex, .katex-display, .katex-inline');
        if (katexElements.length > 0) {
            Array.from(katexElements).forEach(el => {
                info.renderedFormulas.push({
                    element: el,
                    type: el.classList.contains('katex-display') ? 'block' : 'inline'
                });
            });
        }

        return info;
    }

    // ===== 新增：按公式边界分割 =====
    function segmentByFormulaBreaks(blockElement, parentBlockIndex, formulaInfo, debug) {
        if (debug) {
            console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 按公式边界分割，发现${formulaInfo.blockFormulas.length}个块级公式`);
        }

        // 获取所有分割点（句号 + 块级公式边界）
        const rawText = blockElement.textContent || '';
        const breakPoints = [];
        
        // 添加句号分割点
        let sentenceMatch;
        const sentenceRegex = /[。]/g;
        while ((sentenceMatch = sentenceRegex.exec(rawText)) !== null) {
            breakPoints.push(sentenceMatch.index + 1); // +1 to include the period
        }
        
        // 添加公式边界分割点
        formulaInfo.blockFormulas.forEach(formula => {
            breakPoints.push(formula.start);
            breakPoints.push(formula.end);
        });
        
        // 排序并去重
        const uniqueBreakPoints = [...new Set(breakPoints)].sort((a, b) => a - b);
        
        if (uniqueBreakPoints.length <= 2) {
            // 分割点太少，跳过分割
            return;
        }
        
        // 执行分割
        return performSmartSegmentation(blockElement, parentBlockIndex, uniqueBreakPoints, rawText, debug);
    }

    // ===== 新增：行内公式保护分割 =====
    function segmentWithInlineFormulaProtection(blockElement, parentBlockIndex, debug) {
        if (debug) {
            console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 使用行内公式保护分割`);
        }
        
        // 只在句号处分割，避免切断行内公式
        const rawText = blockElement.textContent || '';
        const breakPoints = [0]; // 起始点
        
        let match;
        const sentenceRegex = /[。]/g;
        while ((match = sentenceRegex.exec(rawText)) !== null) {
            breakPoints.push(match.index + 1);
        }
        
        breakPoints.push(rawText.length); // 结束点
        
        if (breakPoints.length <= 2) {
            return; // 没有有效分割点
        }
        
        return performSmartSegmentation(blockElement, parentBlockIndex, breakPoints, rawText, debug);
    }

    // ===== 新增：智能分割执行 =====
    function performSmartSegmentation(blockElement, parentBlockIndex, breakPoints, rawText, debug) {
        let subBlockTrueCounter = 0;
        const newChildNodesContainer = document.createDocumentFragment();
        let firstGeneratedSubBlockElement = null;

        for (let i = 0; i < breakPoints.length - 1; i++) {
            const start = breakPoints[i];
            const end = breakPoints[i + 1];
            const segmentText = rawText.substring(start, end).trim();
            
            if (segmentText.length === 0) continue;
            
            // 创建子块
            const span = document.createElement('span');
            span.className = 'sub-block';
            const subBlockId = `${parentBlockIndex}.${subBlockTrueCounter}`;
            span.dataset.subBlockId = subBlockId;
            span.textContent = segmentText;
            
            if (debug) {
                console.log(`[SubBlockSegmenter] 创建智能子块 #${subBlockId}, 内容: "${segmentText.substring(0, 30)}..."`);
            }
            
            newChildNodesContainer.appendChild(span);
            
            if (subBlockTrueCounter === 0) {
                firstGeneratedSubBlockElement = span;
            } else {
                firstGeneratedSubBlockElement = null;
            }
            
            subBlockTrueCounter++;
        }
        
        if (subBlockTrueCounter > 0) {
            blockElement.innerHTML = '';
            blockElement.appendChild(newChildNodesContainer);
            
            // 标记唯一子块
            if (firstGeneratedSubBlockElement && subBlockTrueCounter === 1) {
                firstGeneratedSubBlockElement.dataset.isOnlySubBlock = "true";
            }
            
            if (debug) {
                console.log(`[SubBlockSegmenter] 块 #${parentBlockIndex} 智能分割完成，生成 ${subBlockTrueCounter} 个子块`);
            }
        }
    }

    global.SubBlockSegmenter = {
        segment: segmentBlockIntoSubBlocks,
        // 暴露新功能用于测试
        checkForFormulas: checkForFormulas,
        analyzeFormulas: analyzeFormulas
    };

})(window);
