"""
最简文档处理器

调度流程：
    PDF结构提取 -> 一级分类 -> 二级分类 -> 组装chunks -> 三级分类

去掉了冗余的 toc_extractor / fulltext_extractor / text_splitter / chunk二级分类。
最终可输出 UnifiedDocumentStructure 或旧版 structured_content 字典。
"""

import asyncio
import uuid
from collections import defaultdict
from typing import Dict, Any, Optional, Tuple, List

from foundation.observability.logger.loggering import review_logger as logger

from .pdf_extractor import PdfStructureExtractor
from .toc_builder import build_toc_items_from_structure
from .chunk_assembler import assemble_chunks
from ..doc_worker.classification.hierarchy_classifier import HierarchyClassifier
from ..doc_worker.classification.chunk_classifier import ChunkClassifier
from ..doc_worker.models import (
    UnifiedDocumentStructure,
    PrimaryClassification,
    SecondaryClassification,
    TertiaryClassification,
    TertiaryItem,
    Outline,
    OutlineItem,
    build_unified_structure,
)


class SimpleDocumentProcessor:
    """最简文档处理器"""

    def __init__(self, use_ocr: bool = False):
        # 从配置读取 OCR 配置
        ocr_api_url = "http://183.220.37.46:25429/v1/chat/completions"
        ocr_api_key = ""
        ocr_timeout = 600

        try:
            from foundation.infrastructure.config.config import config_handler
            ocr_api_url = config_handler.get("ocr", "GLM_OCR_API_URL", ocr_api_url)
            ocr_api_key = config_handler.get("ocr", "GLM_OCR_API_KEY", "")
            ocr_timeout = int(config_handler.get("ocr", "GLM_OCR_TIMEOUT", str(ocr_timeout)))
        except Exception:
            pass

        self.pdf_extractor = PdfStructureExtractor(
            use_ocr=use_ocr,
            ocr_api_url=ocr_api_url,
            ocr_api_key=ocr_api_key,
            ocr_timeout=ocr_timeout,
        )
        self.hierarchy_classifier = HierarchyClassifier()
        self.chunk_classifier = ChunkClassifier()

    async def process_unified(
        self,
        file_content: bytes,
        file_name: str = "",
        progress_callback: Optional[callable] = None,
    ) -> UnifiedDocumentStructure:
        """
        处理 PDF 文档，返回 UnifiedDocumentStructure。
        这是 document_processor 的主要入口。
        """
        structure, primary_result, secondary_result, chunks = await self._run_pipeline(
            file_content, file_name, progress_callback
        )

        if not chunks:
            return self._build_empty_unified(file_name, structure.get("total_pages", 0))

        return self._build_unified_doc(
            structure=structure,
            primary_result=primary_result,
            secondary_result=secondary_result,
            chunks=chunks,
            document_name=file_name,
        )

    async def process(
        self,
        file_content: bytes,
        file_name: str = "",
        progress_callback: Optional[callable] = None,
    ) -> Dict[str, Any]:
        """
        处理 PDF 文档，返回兼容旧版的 structured_content 字典。
        """
        unified = await self.process_unified(file_content, file_name, progress_callback)
        return unified.to_legacy_dict()

    async def _run_pipeline(
        self,
        file_content: bytes,
        file_name: str,
        progress_callback: Optional[callable],
    ) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any], List[Dict[str, Any]]]:
        """执行核心流程，返回 (structure, primary_result, secondary_result, chunks)。"""
        logger.info(f"[SimpleProcessor] 开始处理文档: {file_name}")

        # 1. PDF 结构提取
        structure = self.pdf_extractor.extract(file_content)
        await self._emit_progress(progress_callback, "文档提取", 10, "PDF结构提取完成")

        # 2. 一级分类
        toc_items = build_toc_items_from_structure(structure)
        primary_result = await self.hierarchy_classifier.classify_async(toc_items, target_level=1)
        logger.info(f"[SimpleProcessor] 一级分类完成: {len(primary_result.get('items', []))} 项")
        await self._emit_progress(progress_callback, "文档分类", 25, "一级分类完成")

        # 3. 二级分类
        secondary_result = await self.hierarchy_classifier.classify_secondary_async(primary_result)
        logger.info(f"[SimpleProcessor] 二级分类完成: {secondary_result.get('total_count', 0)} 项")
        await self._emit_progress(progress_callback, "文档分类", 40, "二级分类完成")

        # 4. 组装 chunks
        chunks = assemble_chunks(structure, primary_result, secondary_result)
        if not chunks:
            logger.warning("[SimpleProcessor] 无可用的 chunks")
            return structure, primary_result, secondary_result, chunks
        await self._emit_progress(progress_callback, "文档切分", 50, f"组装 {len(chunks)} 个内容块")

        # 5. 三级分类
        async def _tertiary_progress(completed: int, total: int, section_name: str, success: bool):
            if total > 0:
                current = 60 + int(completed / total * 30)
                status = "完成" if success else "失败"
                await self._emit_progress(
                    progress_callback, "文档分类", current,
                    f"三级分类中：{section_name} {status} [{completed}/{total}]"
                )

        chunks = await self.chunk_classifier.classify_chunks_tertiary_async(
            chunks, progress_callback=_tertiary_progress
        )
        logger.info("[SimpleProcessor] 三级分类完成")
        await self._emit_progress(progress_callback, "文档分类", 90, "三级分类完成")

        return structure, primary_result, secondary_result, chunks

    async def _emit_progress(
        self,
        callback: Optional[callable],
        stage: str,
        current: int,
        message: str,
    ) -> None:
        if callback is None:
            return
        try:
            ret = callback(stage, current, message)
            if asyncio.iscoroutine(ret):
                await ret
        except Exception as e:
            logger.debug(f"[SimpleProcessor] 进度回调异常: {e}")

    def _build_unified_doc(
        self,
        structure: Dict[str, Any],
        primary_result: Dict[str, Any],
        secondary_result: Dict[str, Any],
        chunks: List[Dict[str, Any]],
        document_name: str,
    ) -> UnifiedDocumentStructure:
        """构建 UnifiedDocumentStructure 并合并三级分类结果。"""
        unified = build_unified_structure(
            primary_result=primary_result,
            secondary_result=secondary_result or {"items": []},
            chunks=chunks,
            document_name=document_name,
            total_pages=structure.get("total_pages", 0),
        )

        # 计算总行数
        total_lines = sum(len(c.get("review_chunk_content", "").split("\n")) for c in chunks)
        unified.total_lines = total_lines
        unified.document_id = str(uuid.uuid4())

        # 构建 outline
        outline_items = []
        for sec in unified.secondary_classifications:
            outline_items.append(OutlineItem(
                first_seq=sec.first_seq,
                first_code=sec.first_code,
                first_name=sec.first_name,
                second_seq=sec.second_seq,
                second_code=sec.second_code,
                second_name=sec.second_name,
                raw_title=sec.section_label,
                page=sec.page_start,
            ))
        unified.outline = Outline(items=outline_items)

        # 合并三级分类结果
        self._merge_tertiary_to_unified(unified, chunks)

        # 原始元数据
        unified.raw_metadata = {
            "processing_info": {
                "chunks_count": len(chunks),
                "pages_count": structure.get("total_pages", 0),
            }
        }

        return unified

    def _merge_tertiary_to_unified(
        self,
        unified: UnifiedDocumentStructure,
        chunks: List[Dict[str, Any]],
    ) -> None:
        """将 chunks 中的三级分类详情合并到 UnifiedDocumentStructure。"""
        secondary_groups = defaultdict(lambda: {
            "first_code": "",
            "first_name": "",
            "second_name": "",
            "section_label": "",
            "second_content": "",
            "third_items": [],
        })

        for chunk in chunks:
            first_code = chunk.get("chapter_classification", "")
            second_code = chunk.get("secondary_category_code", "")
            if not second_code or second_code == "none":
                continue

            group = secondary_groups[second_code]
            group["first_code"] = first_code
            group["first_name"] = chunk.get("first_name", "")
            group["second_name"] = chunk.get("second_name", "")
            group["section_label"] = chunk.get("section_label", "")

            content = chunk.get("review_chunk_content", "") or chunk.get("content", "")
            if content:
                if group["second_content"]:
                    group["second_content"] += "\n\n" + content
                else:
                    group["second_content"] = content

            details = chunk.get("tertiary_classification_details", [])
            for detail in details:
                group["third_items"].append(TertiaryItem(
                    third_seq=len(group["third_items"]) + 1,
                    third_code=detail.get("third_category_code", ""),
                    third_name=detail.get("third_category_name", ""),
                    line_start=detail.get("start_line", 0),
                    line_end=detail.get("end_line", 0),
                    content=detail.get("content", ""),
                    confidence=1.0,
                ))

        tertiary_list = []
        second_seq = 0
        for second_code, group in secondary_groups.items():
            if not group["third_items"]:
                continue
            second_seq += 1

            total_lines = len(group["second_content"].split("\n")) if group["second_content"] else 0
            classified_lines = sum(
                item.line_end - item.line_start + 1
                for item in group["third_items"]
            )

            # 查找对应的一级 seq
            first_seq = 99
            for sec in unified.secondary_classifications:
                if sec.second_code == second_code:
                    first_seq = sec.first_seq
                    break

            tertiary_list.append(TertiaryClassification(
                first_seq=first_seq,
                first_code=group["first_code"],
                first_name=group["first_name"],
                second_seq=second_seq,
                second_code=second_code,
                second_name=group["second_name"],
                third_items=group["third_items"],
                total_lines=total_lines,
                classified_lines=classified_lines,
            ))

        unified.tertiary_classifications = tertiary_list

    def _build_empty_unified(self, document_name: str, total_pages: int) -> UnifiedDocumentStructure:
        return UnifiedDocumentStructure(
            document_id=str(uuid.uuid4()),
            document_name=document_name,
            total_pages=total_pages,
            secondary_classifications=[],
        )
