"""
DOCX 目录提取实现

参考 docx_toc_detector.py 的逻辑，识别目录行（标题 + 制表符 + 页码）。
"""

from __future__ import annotations

import re
from pathlib import Path
from typing import Any, Dict, List

from docx import Document

from ..interfaces import TOCExtractor, DocumentSource
from ..utils.toc_level_identifier import TOCLevelIdentifier
from ..utils.toc_pattern_matcher import TOCPatternMatcher


class DocxTOCExtractor(TOCExtractor):
    """DOCX 目录提取器"""

    # 目录行模式：标题 + 制表符 + 页码（页码部分支持带修饰符号，如 ‐ 19 ‐）
    TOC_PATTERN = re.compile(r"^(?P<title>.+?)\t+(?P<page>.*?\d+.*?)\s*$")

    def __init__(self) -> None:
        """初始化 DOCX 目录提取器"""
        self._level_identifier = TOCLevelIdentifier()
        self._page_extractor = TOCPatternMatcher()

    def extract_toc(self, source: DocumentSource) -> Dict[str, Any]:
        """
        提取 DOCX 文档的目录信息
        
        返回结构：
        {
            "toc_items": [{"title": str, "page": int, "level": int, "original": str}, ...],
            "toc_count": int,
            "toc_pages": List[int],
        }
        """
        # 加载文档
        if source.path:
            doc = Document(source.path)
        elif source.content:
            from io import BytesIO
            doc = Document(BytesIO(source.content))
        else:
            raise ValueError("DocumentSource 必须提供 path 或 content")

        # 提取目录行
        toc_items = []
        toc_pages_set = set()
        
        for para in doc.paragraphs:
            text = para.text.strip()
            if "\t" not in text:
                continue
            
            match = self.TOC_PATTERN.match(text)
            if match:
                title = match.group("title").strip()
                page_raw = match.group("page").strip()
                
                # 从可能带有修饰符号的页码中提取纯数字
                page_num_str = self._page_extractor.extract_page_number(page_raw)
                try:
                    page = int(page_num_str)
                except ValueError:
                    # 如果无法转换为整数，跳过该项
                    continue
                
                # 先不设置层级，后续统一识别
                toc_items.append({
                    "title": title,
                    "page": page,
                    "original": text,
                })
                
                toc_pages_set.add(page)

        # 估算目录所在页（假设目录在前几页）
        if toc_items:
            # 目录页通常是目录项中最小页码之前的页
            min_content_page = min(item["page"] for item in toc_items)
            toc_pages = list(range(1, min(min_content_page, 10)))
        else:
            toc_pages = []

        # 使用 TOCLevelIdentifier 识别层级（与 doc_worker 保持一致）
        toc_items = self._level_identifier.identify_levels(toc_items)

        return {
            "toc_items": toc_items,
            "toc_count": len(toc_items),
            "toc_pages": toc_pages,
        }

    def _detect_level(self, title: str) -> int:
        """
        根据标题格式检测层级（已废弃，保留仅用于向后兼容）
        
        注意：此方法已不再使用，现在使用 TOCLevelIdentifier 统一识别层级。
        保留此方法仅用于向后兼容和测试。
        """
        # 章节格式
        if re.match(r"^第[一二三四五六七八九十\d]+章", title):
            return 1
        
        # 中文编号 + 右括号
        if re.match(r"^[一二三四五六七八九十]+[）)]", title):
            return 2
        
        # 数字 + 顿号/句号
        if re.match(r"^\d+[、．.]", title):
            return 3
        
        # 括号数字
        if re.match(r"^[\(（]\d+[\)）]", title):
            return 4
        
        # 默认 level 2
        return 2
