"""docx 标注：在原文加高亮 + 文末追加审核报告附页。"""

from __future__ import annotations

from pathlib import Path

from docx import Document as DocxDocument
from docx.enum.text import WD_BREAK
from docx.shared import Pt
from docx.oxml.ns import qn
from lxml import etree

from fastapi_modules.fastapi_leaudit.govdoc_engine.engine.result import AuditResult


_HIGHLIGHT_NAME = {
    "error": "red",
    "warning": "yellow",
    "info": "cyan",
}


def _highlight_run(run, color_name: str) -> None:
    rpr = run._element.get_or_add_rPr()
    hl = rpr.find(qn("w:highlight"))
    if hl is None:
        hl = etree.SubElement(rpr, qn("w:highlight"))
    hl.set(qn("w:val"), color_name)


def _highlight_paragraph_range(paragraph, start: int, end: int, color_name: str) -> None:
    """简化策略：高亮整段（精准 char range 留 v0.2 实现）。"""
    for run in paragraph.runs:
        _highlight_run(run, color_name)


def _add_heading_with_fallback(doc, text: str, level: int = 1):
    try:
        return doc.add_heading(text, level=level)
    except KeyError:
        # Some uploaded documents don't include Word's built-in heading styles.
        p = doc.add_paragraph()
        run = p.add_run(text)
        run.bold = True
        if level == 1:
            run.font.size = Pt(16)
        elif level == 2:
            run.font.size = Pt(13)
        else:
            run.font.size = Pt(12)
        return p


def _append_appendix(doc, result: AuditResult) -> None:
    p = doc.add_paragraph()
    p.add_run().add_break(WD_BREAK.PAGE)
    _add_heading_with_fallback(doc, "审核报告附页", level=1)

    s = result.summary
    doc.add_paragraph(
        f"得分: {s.score}/100   错误: {s.by_severity.get('error', 0)}   "
        f"警告: {s.by_severity.get('warning', 0)}   提示: {s.by_severity.get('info', 0)}"
    )

    if not result.findings:
        doc.add_paragraph("未发现问题。")
        return

    table = doc.add_table(rows=1, cols=5)
    try:
        table.style = "Light Grid"
    except KeyError:
        # Some source documents don't ship with the built-in table style set.
        pass
    hdr = table.rows[0].cells
    for i, h in enumerate(["编号", "规则", "严重度", "类别", "位置 / 说明"]):
        hdr[i].text = h

    for f in result.findings:
        row = table.add_row().cells
        row[0].text = f.finding_id
        row[1].text = f.rule_id
        row[2].text = f.severity
        row[3].text = f.category
        loc = f.location
        ctx = (loc.context or "")[:30]
        row[4].text = f"P{loc.paragraph_index} ({loc.role}): {f.message}\n  原文: {ctx}"


def annotate_docx(src: str | Path, dst: str | Path, result: AuditResult) -> None:
    src = Path(src)
    dst = Path(dst)
    doc = DocxDocument(src)

    for f in result.findings:
        idx = f.location.paragraph_index
        if 0 <= idx < len(doc.paragraphs):
            color = _HIGHLIGHT_NAME.get(f.severity, "yellow")
            _highlight_paragraph_range(
                doc.paragraphs[idx], f.location.char_start, f.location.char_end, color
            )

    _append_appendix(doc, result)
    dst.parent.mkdir(parents=True, exist_ok=True)
    doc.save(dst)
