"""
文本块切分模块
用于将文本按子标题进行切分
"""

import re

try:
    from ..config.config_loader import get_config
    from .title_matcher import TitleMatcher
except ImportError:
    from config.config_loader import get_config
    from title_matcher import TitleMatcher


class ChunkSplitter:
    """文本块切分器"""
    
    def __init__(self):
        self.config = get_config()
        self.title_matcher = TitleMatcher()
    
    def split_by_sub_titles(self, content_block, all_toc_items, parent_title_info, 
                            target_level, max_chunk_size, min_chunk_size, full_text=None, 
                            block_start_pos=0, parent_hierarchy_path=None):
        """
        在正文块中按子标题进行切分（按照toc_items的顺序和层级关系）
        
        参数:
            content_block: 正文块内容
            all_toc_items: 所有目录项（有序列表）
            parent_title_info: 父标题信息
            target_level: 目标层级
            max_chunk_size: 最大分块字符数
            min_chunk_size: 最小分块字符数
            full_text: 全文内容（已废弃，保留以兼容）
            block_start_pos: 正文块在全文中的起始位置（已废弃，保留以兼容）
            parent_hierarchy_path: 父标题的层级路径（已废弃，保留以兼容）
            
        返回:
            list: 子块列表
        """
        # 找到父标题在toc_items中的位置
        parent_title = parent_title_info['title']
        parent_idx = -1
        for idx, toc_item in enumerate(all_toc_items):
            if toc_item['title'] == parent_title and toc_item.get('level', 1) == target_level:
                parent_idx = idx
                break
        
        if parent_idx < 0:
            # 如果找不到父标题，回退到原来的逻辑
            return self._split_by_finding_subtitles(content_block, all_toc_items, parent_title_info, 
                                                    target_level, max_chunk_size, min_chunk_size)
        
        # 按照toc_items的顺序，找到所有属于当前父标题的子标题
        # 子标题的定义：level > target_level，且在toc_items中位于当前父标题之后、下一个同级标题之前
        sub_titles = []
        fuzzy_threshold = self.config.fuzzy_threshold
        
        # 找到下一个同级标题的位置
        next_sibling_idx = len(all_toc_items)
        for idx in range(parent_idx + 1, len(all_toc_items)):
            item = all_toc_items[idx]
            if item.get('level', 1) <= target_level:
                next_sibling_idx = idx
                break
        
        # 在toc_items中查找子标题，并在正文块中定位它们
        for idx in range(parent_idx + 1, next_sibling_idx):
            toc_item = all_toc_items[idx]
            if toc_item.get('level', 1) > target_level:
                # 在正文块中查找这个子标题
                pos = self.title_matcher.find_title_in_text(toc_item['title'], content_block, fuzzy_threshold=fuzzy_threshold)
                if pos >= 0:
                    sub_titles.append({
                        'title': toc_item['title'],
                        'level': toc_item['level'],
                        'position': pos,
                        'toc_index': idx,
                        'toc_item': toc_item
                    })
        
        # 按位置排序（确保在正文中的顺序正确）
        sub_titles.sort(key=lambda x: x['position'])
        
        # 如果没有找到子标题，将整个正文块作为一个块
        if not sub_titles:
            # 检查是否需要分割
            if len(content_block) > max_chunk_size:
                return self.split_large_chunk(content_block, max_chunk_size, parent_title_info['title'], [])
            else:
                return [{
                    'content': content_block,
                    'relative_start': 0,
                    'sub_title': '',
                    'serial_number': '',
                    'hierarchy_path': []
                }]
        
        # 按子标题切分
        chunks = []
        for i, sub_title in enumerate(sub_titles):
            start_pos = sub_title['position']
            
            # 确定结束位置
            if i + 1 < len(sub_titles):
                end_pos = sub_titles[i + 1]['position']
            else:
                end_pos = len(content_block)
            
            chunk_content = content_block[start_pos:end_pos]
            
            # 检查子标题是否有实际正文内容（去除标题后是否还有内容）
            # 移除标题行，检查剩余内容
            title_len = len(sub_title['title'])
            content_after_title = chunk_content[title_len:].strip()
            
            # 如果去除标题后没有实际内容，跳过这个块（不创建chunk）
            if not content_after_title or len(content_after_title) < 10:
                continue
            
            # 构建层级路径
            hierarchy_path = self._build_hierarchy_path_for_subtitle(sub_title['toc_item'], all_toc_items, parent_title_info)
            
            # 检查是否需要分割
            if len(chunk_content) > max_chunk_size:
                split_chunks = self.split_large_chunk(chunk_content, max_chunk_size, sub_title['title'], hierarchy_path)
                for j, split_chunk in enumerate(split_chunks):
                    split_chunk['relative_start'] = start_pos + split_chunk['relative_start']
                    split_chunk['sub_title'] = sub_title['title']
                    if 'hierarchy_path' not in split_chunk:
                        split_chunk['hierarchy_path'] = hierarchy_path
                    chunks.append(split_chunk)
            else:
                chunks.append({
                    'content': chunk_content,
                    'relative_start': start_pos,
                    'sub_title': sub_title['title'],
                    'hierarchy_path': hierarchy_path
                })
        
        # 如果所有子标题都没有正文内容，返回整个正文块
        if not chunks:
            if len(content_block) > max_chunk_size:
                return self.split_large_chunk(content_block, max_chunk_size, parent_title_info['title'], [])
            else:
                return [{
                    'content': content_block,
                    'relative_start': 0,
                    'sub_title': '',
                    'serial_number': '',
                    'hierarchy_path': []
                }]
        
        return chunks
    
    def _split_by_finding_subtitles(self, content_block, all_toc_items, parent_title_info, 
                                    target_level, max_chunk_size, min_chunk_size):
        """
        回退方法：在正文块中查找子标题（原有逻辑）
        """
        sub_titles = []
        fuzzy_threshold = self.config.fuzzy_threshold
        for toc_item in all_toc_items:
            if toc_item['level'] > target_level:
                pos = self.title_matcher.find_title_in_text(toc_item['title'], content_block, fuzzy_threshold=fuzzy_threshold)
                if pos >= 0:
                    sub_titles.append({
                        'title': toc_item['title'],
                        'level': toc_item['level'],
                        'position': pos
                    })
        
        sub_titles.sort(key=lambda x: x['position'])
        
        if not sub_titles:
            if len(content_block) > max_chunk_size:
                return self.split_large_chunk(content_block, max_chunk_size, parent_title_info['title'], [])
            else:
                return [{
                    'content': content_block,
                    'relative_start': 0,
                    'sub_title': '',
                    'serial_number': '',
                    'hierarchy_path': []
                }]
        
        chunks = []
        for i, sub_title in enumerate(sub_titles):
            start_pos = sub_title['position']
            if i + 1 < len(sub_titles):
                end_pos = sub_titles[i + 1]['position']
            else:
                end_pos = len(content_block)
            
            chunk_content = content_block[start_pos:end_pos]
            
            if len(chunk_content) > max_chunk_size:
                split_chunks = self.split_large_chunk(chunk_content, max_chunk_size, sub_title['title'], [])
                for j, split_chunk in enumerate(split_chunks):
                    split_chunk['relative_start'] = start_pos + split_chunk['relative_start']
                    split_chunk['sub_title'] = sub_title['title']
                    if 'hierarchy_path' not in split_chunk:
                        split_chunk['hierarchy_path'] = []
                    chunks.append(split_chunk)
            else:
                chunks.append({
                    'content': chunk_content,
                    'relative_start': start_pos,
                    'sub_title': sub_title['title'],
                    'hierarchy_path': []
                })
        
        return chunks
    
    def _build_hierarchy_path_for_subtitle(self, sub_title_item, all_toc_items, parent_title_info):
        """
        为子标题构建完整的层级路径
        
        参数:
            sub_title_item: 子标题的toc_item（字典）
            all_toc_items: 所有目录项
            parent_title_info: 父标题信息
            
        返回:
            list: 层级路径列表，从1级到当前子标题
        """
        hierarchy_path = []
        
        # 找到子标题在toc_items中的位置（通过标题匹配）
        sub_title = sub_title_item.get('title', '')
        sub_title_idx = -1
        for idx, item in enumerate(all_toc_items):
            if item.get('title', '') == sub_title:
                sub_title_idx = idx
                break
        
        if sub_title_idx < 0:
            # 如果找不到，返回父标题->子标题
            return [parent_title_info['title'], sub_title]
        
        # 从子标题向前查找，找到每个层级的父级标题
        level_paths = {}  # 存储每个层级对应的标题
        current_level = sub_title_item.get('level', 2)
        
        for i in range(sub_title_idx, -1, -1):
            item = all_toc_items[i]
            item_level = item.get('level', 1)
            
            if item_level <= current_level and item_level not in level_paths:
                level_paths[item_level] = item['title']
                if item_level == 1:
                    break
        
        # 按层级顺序构建路径（从1级到当前层级）
        for level in range(1, current_level + 1):
            if level in level_paths:
                hierarchy_path.append(level_paths[level])
        
        # 如果路径为空，至少包含父标题和子标题
        if not hierarchy_path:
            hierarchy_path = [parent_title_info['title'], sub_title]
        
        return hierarchy_path
    
    def split_large_chunk(self, content, max_chunk_size, title, hierarchy_path=None):
        """
        将超大块按句子级分割（保持语义完整）
        
        参数:
            content: 内容
            max_chunk_size: 最大分块字符数
            title: 标题
            hierarchy_path: 层级路径（可选）
            
        返回:
            list: 分割后的块列表
        """
        # 按句子分割（中文句号、问号、感叹号）
        sentences = re.split(r'([。！？\n])', content)
        
        # 重新组合句子和标点
        combined_sentences = []
        for i in range(0, len(sentences) - 1, 2):
            if i + 1 < len(sentences):
                combined_sentences.append(sentences[i] + sentences[i + 1])
            else:
                combined_sentences.append(sentences[i])
        
        if not combined_sentences:
            combined_sentences = [content]
        
        # 按max_chunk_size组合句子
        chunks = []
        current_chunk = ""
        current_start = 0
        
        for sentence in combined_sentences:
            if len(current_chunk) + len(sentence) <= max_chunk_size:
                current_chunk += sentence
            else:
                if current_chunk:
                    chunk_data = {
                        'content': current_chunk,
                        'relative_start': current_start,
                        'is_split': True  # 标记为分割块，不参与合并
                    }
                    if hierarchy_path is not None:
                        chunk_data['hierarchy_path'] = hierarchy_path
                    chunks.append(chunk_data)
                    current_start += len(current_chunk)
                current_chunk = sentence
        
        # 添加最后一个块
        if current_chunk:
            chunk_data = {
                'content': current_chunk,
                'relative_start': current_start,
                'is_split': True
            }
            if hierarchy_path is not None:
                chunk_data['hierarchy_path'] = hierarchy_path
            chunks.append(chunk_data)
        
        return chunks


