"""
目录层级识别工具

与原 doc_worker 中的 TOCLevelIdentifier 逻辑等价，
用于根据格式规则模板识别各目录项的层级。

改进：当格式模板无法识别时，作为兜底方案使用数字编号识别。
"""

from __future__ import annotations

import re
from typing import Any, Dict, List, Optional

from ..config.provider import default_config_provider


class TOCLevelIdentifier:
    """目录层级识别器。"""

    def __init__(self) -> None:
        self._cfg = default_config_provider

    def _templates(self) -> List[Dict[str, Any]]:
        return self._cfg.get("format_patterns.templates", [])

    def match_format_pattern(self, text: str) -> Optional[Dict[str, Any]]:
        """匹配文本的格式模式。"""
        for template_info in self._templates():
            pattern = template_info.get("pattern", "")
            if pattern and re.match(pattern, text):
                return {
                    "pattern": pattern,
                    "template": template_info.get("template", ""),
                    "name": template_info.get("name", ""),
                }
        return None

    def get_format_key(self, format_info: Dict[str, Any]) -> str:
        """获取格式的唯一标识（用于比较）。"""
        return format_info.get("template", "")
    
    def _extract_numbering_level(self, text: str) -> Optional[int]:
        """
        从标题中提取编号的层级深度（兜底方案）。
        
        仅在格式模板无法识别时使用。
        """
        # 按优先级从高到低检查
        
        # 四级数字点号格式：1.1.1.1.
        if re.match(r'^\d+\.\d+\.\d+\.\d+\.', text):
            return 4
        
        # 四级数字编号格式：1.1.1.1
        if re.match(r'^\d+\.\d+\.\d+\.\d+(?:\s|、|．|$)', text):
            return 4
        
        # 三级数字点号格式：1.1.1.
        if re.match(r'^\d+\.\d+\.\d+\.', text):
            return 3
        
        # 三级数字编号格式：1.1.1
        if re.match(r'^\d+\.\d+\.\d+(?:\s|、|．|$)', text):
            return 3
        
        # 二级数字点号格式：1.1.
        if re.match(r'^\d+\.\d+\.', text):
            return 2
        
        # 二级数字编号格式：1.1
        if re.match(r'^\d+\.\d+(?:\s|、|．|$)', text):
            return 2
        
        # 纯数字点号格式：1.
        if re.match(r'^\d+\.(?:\s|$)', text):
            return 1
        
        # 一级数字编号格式：1（后面必须有空格、标点或结束）
        if re.match(r'^\d+(?:\s|、|．|$)', text):
            return 1
        
        return None

    def _has_multi_level_numbering(self, toc_items: List[Dict[str, Any]]) -> bool:
        """
        检测目录中是否存在多级数字点号编号格式（如 1.2.3）。
        
        如果存在这种格式，说明编号本身已经包含了层级信息，
        应该按编号中的数字个数进行层级分配，而不是使用递归逻辑。
        """
        for item in toc_items:
            title = item.get("title", "")
            # 检测多级数字点号格式：至少包含两个点号的数字编号
            if re.match(r'^\d+\.\d+(?:\.\d+)*(?:\s|、|．|$)', title):
                return True
        return False

    def _assign_levels_by_numbering(self, toc_items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """
        按编号中的数字个数进行层级分配（非递归方式）。
        
        例如：
        - 1 -> level 1
        - 1.1 -> level 2
        - 1.1.1 -> level 3
        - 1.1.1.1 -> level 4
        """
        for item in toc_items:
            title = item.get("title", "")
            # 提取编号部分（数字和点号）
            match = re.match(r'^(\d+(?:\.\d+)*)', title)
            if match:
                numbering = match.group(1)
                # 计算点号个数 + 1 = 层级
                level = numbering.count('.') + 1
                item["level"] = level
            else:
                # 如果无法识别编号，设为一级
                item["level"] = 1
        return toc_items

    def identify_levels(self, toc_items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """识别目录层级（第一个项一定是一级目录）。"""
        if not toc_items:
            return toc_items

        # 先检测是否存在多级数字点号编号格式
        if self._has_multi_level_numbering(toc_items):
            # 如果存在，直接按编号中的数字个数进行层级分配
            return self._assign_levels_by_numbering(toc_items)

        # 否则，使用原有的递归层级校对逻辑
        first_item = toc_items[0]
        first_item["level"] = 1

        first_format_info = self.match_format_pattern(first_item["title"])
        if not first_format_info:
            # 第一项无法匹配格式模板
            # 尝试用数字编号识别后续项的层级
            for item in toc_items[1:]:
                fmt = self.match_format_pattern(item["title"])
                if fmt:
                    # 如果能匹配格式模板，设为一级（作为新的一级项）
                    item["level"] = 1
                else:
                    # 如果无法匹配格式模板，尝试用数字编号识别
                    numbering_level = self._extract_numbering_level(item["title"])
                    if numbering_level is not None:
                        item["level"] = numbering_level
                    else:
                        # 如果仍无法识别，设为一级
                        item["level"] = 1
            return toc_items

        first_key = self.get_format_key(first_format_info)

        level1_indices = [0]
        for i in range(1, len(toc_items)):
            item = toc_items[i]
            fmt = self.match_format_pattern(item["title"])
            if not fmt:
                # 无法匹配格式模板，尝试用数字编号识别
                numbering_level = self._extract_numbering_level(item["title"])
                if numbering_level is not None:
                    item["level"] = numbering_level
                continue
            if self.get_format_key(fmt) == first_key:
                item["level"] = 1
                level1_indices.append(i)

        # 递归处理一级目录下的子项
        for i in range(len(level1_indices)):
            level1_idx = level1_indices[i]
            if i < len(level1_indices) - 1:
                next_level1_idx = level1_indices[i + 1]
                child_start = level1_idx + 1
                child_end = next_level1_idx
            else:
                child_start = level1_idx + 1
                child_end = len(toc_items)

            if child_start < child_end:
                self._identify_levels_recursive(toc_items, level=2, start_idx=child_start, end_idx=child_end)

        return toc_items

    def _identify_levels_recursive(self, items: List[Dict[str, Any]], level: int, start_idx: int, end_idx: int) -> None:
        """递归识别子项的层级。"""
        if start_idx >= end_idx:
            return

        current_items = items[start_idx:end_idx]
        if not current_items:
            return

        first_item = current_items[0]
        first_item["level"] = level

        fmt_info = self.match_format_pattern(first_item["title"])
        if not fmt_info:
            # 第一项无法匹配格式模板
            # 尝试用数字编号识别后续项的层级
            for item in current_items[1:]:
                fmt = self.match_format_pattern(item["title"])
                if fmt:
                    # 如果能匹配格式模板，设为当前级（作为新的同级项）
                    item["level"] = level
                else:
                    # 如果无法匹配格式模板，尝试用数字编号识别
                    numbering_level = self._extract_numbering_level(item["title"])
                    if numbering_level is not None:
                        item["level"] = numbering_level
                    else:
                        # 如果仍无法识别，设为当前级
                        item["level"] = level
            return

        first_key = self.get_format_key(fmt_info)
        same_level_indices = [0]

        for i in range(1, len(current_items)):
            item = current_items[i]
            fmt = self.match_format_pattern(item["title"])
            if not fmt:
                # 无法匹配格式模板，尝试用数字编号识别
                numbering_level = self._extract_numbering_level(item["title"])
                if numbering_level is not None:
                    item["level"] = numbering_level
                continue
            if self.get_format_key(fmt) == first_key:
                same_level_indices.append(i)
                item["level"] = level

        for i in range(len(same_level_indices)):
            current_level_idx = start_idx + same_level_indices[i]

            if i < len(same_level_indices) - 1:
                next_level_idx = start_idx + same_level_indices[i + 1]
                child_start = current_level_idx + 1
                child_end = next_level_idx
            else:
                child_start = current_level_idx + 1
                child_end = end_idx

            if child_start < child_end:
                self._identify_levels_recursive(items, level + 1, child_start, child_end)








