"""
文本块元数据模块
用于构建和处理文本块的元数据
"""

from pathlib import Path

try:
    from .text_utils import TextUtils
    from .title_matcher import TitleMatcher
except ImportError:
    from text_utils import TextUtils
    from title_matcher import TitleMatcher


class ChunkMetadata:
    """文本块元数据构建器"""
    
    def __init__(self):
        self.text_utils = TextUtils()
        self.title_matcher = TitleMatcher()
    
    def build_chunk_metadata(self, sub_chunk, title_info, start_pos, pages_content, i, j):
        """
        构建文本块的元数据
        
        参数:
            sub_chunk: 子块信息
            title_info: 标题信息
            start_pos: 起始位置
            pages_content: 页面内容列表
            i: 标题索引
            j: 子块索引
            
        返回:
            dict: 文本块元数据
        """
        # 计算实际页码
        chunk_start_pos = start_pos + sub_chunk['relative_start']
        page_num = self.title_matcher.get_page_number(chunk_start_pos, pages_content)
        
        # 构建section_label：使用完整的层级路径
        hierarchy_path = sub_chunk.get('hierarchy_path', [])
        sub_title = sub_chunk.get('sub_title', '')
        
        if hierarchy_path:
            # 使用层级路径构建section_label
            section_label = '->'.join(hierarchy_path)
        elif sub_title:
            # 如果没有层级路径但有子标题，使用父标题->子标题
            section_label = f"{title_info['title']}->{sub_title}"
        else:
            # 如果没有子标题，尝试从内容开头提取可能的标题信息
            content_start = sub_chunk.get('content', '').strip()
            extracted_title = self._extract_title_from_content(content_start)
            if extracted_title:
                section_label = f"{title_info['title']}->{extracted_title}"
            else:
                # 如果无法提取，使用父标题
                section_label = title_info['title']
        
        # 提取最低层级标题的编号（按照测试目录的逻辑）
        # 优先使用层级路径中的最后一个标题（最低层级）
        if hierarchy_path:
            lowest_title = hierarchy_path[-1]
            title_number = self._extract_title_number(lowest_title)
        elif sub_title:
            title_number = self._extract_title_number(sub_title)
        else:
            # 尝试从内容中提取
            content_start = sub_chunk.get('content', '').strip()
            extracted_title = self._extract_title_from_content(content_start)
            if extracted_title:
                title_number = self._extract_title_number(extracted_title)
            else:
                # 如果没有子标题，从父标题提取
                title_number = self._extract_title_number(title_info['title'])
        
        # 构建chunk_id格式：doc_chunk_<serial_number>_<序号>
        chunk_id_str = f"doc_chunk_{title_number}_{j}" if title_number else f"doc_chunk_{j}"
        
        return {
            'file_name': Path(pages_content[0].get('source_file', 'unknown')).name if pages_content else 'unknown',
            'chunk_id': chunk_id_str,
            'section_label': section_label,
            'project_plan_type': 'bridge_up_part',
            'element_tag': {
                'chunk_id': chunk_id_str,
                'page': page_num,
                'serial_number': title_number if title_number else str(i + 1)
            },
            'review_chunk_content': sub_chunk['content'],
            '_title_number': title_number,  # 临时存储，用于合并时判断
            '_local_index': j  # 临时存储局部索引
        }
    
    def finalize_chunk_ids(self, chunks):
        """
        生成最终的chunk_id和serial_number
        
        参数:
            chunks: 合并后的块列表
            
        返回:
            list: 最终处理后的块列表
        """
        final_chunks = []
        current_title_number = None
        local_index = 1
        prev_was_merged = False  # 标记上一个块是否是跨标题合并的块
        
        for i, chunk in enumerate(chunks):
            title_number = chunk.get('_title_number', '')
            is_merged = chunk.get('_is_merged', False)
            section_label = chunk.get('section_label', '')
            
            # 提取标题编号的主要部分（用于判断是否在同一标题内）
            # 如果包含+号，说明是跨标题合并的块
            if '+' in str(title_number):
                # 跨标题合并的块，序号为0
                local_index = 0
                # 提取第二个标题编号（合并块算入第二个标题）
                second_title = title_number.split('+')[1]
                current_title_number = second_title
                prev_was_merged = True
                merged_title_number = title_number
            else:
                # 如果标题编号变化，重置索引
                if title_number != current_title_number:
                    current_title_number = title_number
                    # 如果上一个块是跨标题合并的，且当前标题是第二个标题
                    # 说明这是第二个标题的第一个非合并块，从1开始
                    if prev_was_merged:
                        local_index = 1
                        prev_was_merged = False
                    else:
                        # 新标题，从1开始
                        local_index = 1
                else:
                    # 同一标题内，递增
                    local_index += 1
                merged_title_number = title_number
            
            # 从section_label中提取标题路径的编号路径（用于chunk_id）
            title_number_path = self._extract_title_number_path(section_label)
            
            # 生成chunk_id：doc_chunk_<标题路径的编号路径>_序号
            if title_number_path:
                chunk_id_str = f"doc_chunk_{title_number_path}_{local_index}"
            elif merged_title_number:
                # 如果没有完整的编号路径，使用合并后的编号（向后兼容）
                chunk_id_str = f"doc_chunk_{merged_title_number}_{local_index}"
            else:
                chunk_id_str = f"doc_chunk_{local_index}"
            
            # 从section_label中提取最底层级的编号（用于serial_number）
            serial_number = self.text_utils.extract_number_from_section_label(section_label)
            
            # 更新chunk数据
            final_chunk = {
                'file_name': chunk['file_name'],
                'chunk_id': chunk_id_str,
                'section_label': chunk['section_label'],
                'project_plan_type': 'bridge_up_part',
                'element_tag': {
                    'chunk_id': chunk_id_str,
                    'page': chunk['element_tag']['page'],
                    'serial_number': serial_number
                },
                'review_chunk_content': chunk['review_chunk_content']
            }
            
            final_chunks.append(final_chunk)
        
        return final_chunks
    
    def _extract_title_from_content(self, content):
        """
        从内容开头提取可能的标题信息
        
        参数:
            content: 内容字符串
            
        返回:
            str: 提取的标题，如果未找到则返回空字符串
        """
        if not content:
            return ""
        
        import re
        # 只检查前200个字符（标题通常在内容开头）
        content_start = content[:200].strip()
        
        # 先尝试匹配第一行（标题通常在单独的一行）
        first_line = content_start.split('\n')[0].strip()
        if not first_line:
            return ""
        
        # 匹配常见的标题格式
        # 1. 双方括号格式：〖1.1〗标题
        pattern1 = re.match(r'^(〖\d+(?:\.\d+)*〗[^\n]+)', first_line)
        if pattern1:
            title = pattern1.group(1).strip()
            # 限制标题长度，避免提取过多内容
            if len(title) <= 100:
                return title
        
        # 2. 方括号格式：【1】标题
        pattern2 = re.match(r'^(【\d+】[^\n]+)', first_line)
        if pattern2:
            title = pattern2.group(1).strip()
            if len(title) <= 100:
                return title
        
        # 3. 数字编号格式：1.1 标题 或 1.1.1 标题
        pattern3 = re.match(r'^(\d+(?:\.\d+)+[^\s\n]+(?:\s+[^\s\n]+)?)', first_line)
        if pattern3:
            title = pattern3.group(1).strip()
            if len(title) <= 100:
                return title
        
        # 4. 中文编号格式：一、标题 或 （一）标题
        pattern4 = re.match(r'^([一二三四五六七八九十]+[、．.][^\n]+)', first_line)
        if pattern4:
            title = pattern4.group(1).strip()
            if len(title) <= 100:
                return title
        
        # 5. 括号编号格式：（1）标题 或 （一）标题
        pattern5 = re.match(r'^([（(][一二三四五六七八九十\d]+[）)][^\n]+)', first_line)
        if pattern5:
            title = pattern5.group(1).strip()
            if len(title) <= 100:
                return title
        
        return ""
    
    def _extract_title_number(self, title):
        """
        从标题中提取编号部分（复用测试目录的逻辑）
        
        例如：
        "1.5 施工条件" -> "1.5"
        "1.6 风险辨识与分级" -> "1.6"
        "1 工程概况" -> "1"
        
        参数:
            title: 标题字符串
            
        返回:
            str: 编号部分，如果未找到则返回空字符串
        """
        import re
        # 匹配数字编号格式（如 1.5, 1.6, 1.2.3等）
        number_match = re.match(r'^(\d+(?:\.\d+)*)', title)
        if number_match:
            return number_match.group(1)
        
        # 匹配中文编号格式（如 一、二、三等）
        chinese_match = re.match(r'^([一二三四五六七八九十]+)[、．.]', title)
        if chinese_match:
            return chinese_match.group(1)
        
        return ""
    
    def _extract_title_number_path(self, section_label):
        """
        从section_label中提取标题路径的编号路径
        
        例如：
        "第一章 工程概况->【1】工程概况->1.1 项目总体概况" -> "1->【1】->1.1"
        "第三章 施工计划->【2】机械设备计划" -> "3->【2】"
        "第一章 工程概况->【2】自然条件->2.1 气象情况" -> "1->【2】->2.1"
        
        参数:
            section_label: section_label字符串，格式为 "一级->二级->三级"
            
        返回:
            str: 编号路径，用"->"连接，如果未找到则返回空字符串
        """
        if not section_label:
            return ""
        
        # 处理合并的情况（用" + "连接），取第一部分
        if ' + ' in section_label:
            section_label = section_label.split(' + ')[0]
        
        # 按"->"分割层级路径
        parts = section_label.split('->')
        
        # 提取每一层的编号
        number_paths = []
        for part in parts:
            part = part.strip()
            if part:
                # 使用text_utils的extract_title_number方法提取编号
                number = self.text_utils.extract_title_number(part)
                if number:
                    number_paths.append(number)
        
        # 用"->"连接编号路径
        if number_paths:
            return '->'.join(number_paths)
        
        return ""
    
    def build_hierarchy_path(self, title, all_toc_items, target_level):
        """
        构建从1级到当前标题的完整层级路径
        
        参数:
            title: 当前标题
            all_toc_items: 所有目录项列表
            target_level: 目标层级
            
        返回:
            list: 层级路径列表，从1级到当前层级
        """
        hierarchy_path = []
        
        # 找到当前标题在目录中的位置
        current_item = None
        current_idx = -1
        for idx, item in enumerate(all_toc_items):
            if item['title'] == title:
                current_item = item
                current_idx = idx
                break
        
        if not current_item:
            # 如果找不到，返回只包含当前标题的路径
            return [title]
        
        current_level = current_item.get('level', target_level)
        
        # 从当前项向前查找，找到每个层级的最近父级
        level_paths = {}  # 存储每个层级对应的标题
        
        # 从当前项向前遍历，找到所有层级的父级
        for i in range(current_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']
                
                # 如果已经找到了1级，就可以停止了
                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])
            elif level == current_level:
                # 如果当前层级没有找到，使用当前标题
                hierarchy_path.append(title)
        
        # 如果路径为空，至少包含当前标题
        if not hierarchy_path:
            hierarchy_path = [title]
        
        return hierarchy_path


