"""
DOCX 全文提取实现

提取 DOCX 文档的全文内容，按段落组织，模拟分页。
"""

from __future__ import annotations

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

from docx import Document

from ..interfaces import FullTextExtractor, DocumentSource


class DocxFullTextExtractor(FullTextExtractor):
    """DOCX 全文提取器"""

    def __init__(self, paragraphs_per_page: int = 30):
        """
        初始化
        
        Args:
            paragraphs_per_page: 每页段落数（用于模拟分页）
        """
        self.paragraphs_per_page = paragraphs_per_page

    def extract_full_text(self, source: DocumentSource) -> List[Dict[str, Any]]:
        """
        提取 DOCX 文档的全文内容
        
        返回结构：
        [
            {
                "page_num": int,
                "text": str,
                "start_pos": int,
                "end_pos": int,
                "source_file": str,
            },
            ...
        ]
        """
        # 加载文档
        if source.path:
            doc = Document(source.path)
            source_file = str(source.path)
        elif source.content:
            doc = Document(BytesIO(source.content))
            source_file = "bytes_stream"
        else:
            raise ValueError("DocumentSource 必须提供 path 或 content")

        # 按照文档中的实际顺序提取段落和表格
        # 创建段落和表格的元素到对象的映射
        para_map = {para._element: para for para in doc.paragraphs}
        table_map = {table._element: table for table in doc.tables}
        
        # 按照文档中的顺序遍历所有元素
        all_elements = []
        for element in doc.element.body:
            if element in para_map:
                # 段落元素
                para = para_map[element]
                text = para.text
                # 过滤目录行：标题\t页码（页码部分支持带修饰符号）
                # 匹配从开头开始，包含制表符且末尾有数字的模式（目录行特征）
                if text and not re.match(r"^.+\t+.*?\d+.*?\s*$", text):
                    all_elements.append(text)
            elif element in table_map:
                # 表格元素
                table = table_map[element]
                table_text = self._extract_table_text(table)
                all_elements.append(table_text)

        # 模拟分页：每 N 个元素作为一页
        pages_content = []
        current_pos = 0
        
        # 正则表达式：匹配 [表格开始]...任意内容...[表格结束] 模式
        table_placeholder_pattern = re.compile(
            r'\n?\[表格开始\]\n.*?\n\[表格结束\]\n?',
            re.DOTALL
        )
        
        for page_num in range(0, len(all_elements), self.paragraphs_per_page):
            page_elements = all_elements[page_num:page_num + self.paragraphs_per_page]
            page_text = "\n".join(page_elements)
            
            # 将任何可能存在的 [表格开始]...表格内容...[表格结束] 替换为占位符
            page_text = table_placeholder_pattern.sub('\n<表格></表格>\n', page_text)
            
            pages_content.append({
                "page_num": page_num // self.paragraphs_per_page + 1,
                "text": page_text,
                "start_pos": current_pos,
                "end_pos": current_pos + len(page_text),
                "source_file": source_file,
            })
            
            current_pos += len(page_text)

        return pages_content

    def _extract_table_text(self, table) -> str:
        """提取表格占位符，不提取实际内容"""
        return "\n<表格></表格>\n"
