#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
报告通用清洗器（基于铁律 v1.0）
================================
针对历史报告自动修复以下问题，使其通过 pre_release_gate 校验：
- 删除骨架装饰（长官铺垫、对您忠诚、呈报人等）
- 删除元工作流痕迹与工具元数据区段
- 清除 markdown 残留（粗体、分隔线、项目符号）
- 修复段落格式（left=None, first_line=2字符）
- 清除 numPr 列表样式

用法：python repair_legacy_reports.py <docx路径或目录>
"""
import os
import re
import sys
import glob
from docx import Document
from docx.shared import Emu

WORDML_NS = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
TARGET_INDENT = Emu(406400)

# === 整行/整段删除模式 ===
LINE_DELETE_PATTERNS = [
    r"本次搜索",
    r"建议下一步",
    r"宁可省略",
    r"按技能要求",
    r"按您的指示",
    r"已纳入信源池",
    r"twscrape",
    r"DuckDuckGo",
    r"已验证 status",
    r"^长官[：:]\s*按照您的指示",
    r"对您忠诚",
    r"^呈报人[：:]",
    r"呈报人[：:]\s*瞰宇",
    r"报告完成时间[：:]",
    r"瞰宇（全球数据采集师",
    r"^信源类型分布",
    r"^信源国家分布",
    r"^禁用媒体过滤",
    r"^验证方法",
    r"^验证通过率",
    r"^[-\s·•・]*验证通过率",
    r"^[-\s·•・]*参考文献总数",
    r"^[-\s·•・]*验证状态",
    r"^[-\s·•・]*验证时间",
    r"^[-\s·•・]*因服务器限制无法",
    r"^[-\s·•・]*独立验证",
    r"^[-\s·•・]*域名权重",
    r"^参考文献总数",
    r"^域名权重",
    r"^本报告基于\s*\d+\s*条已验证\s*URL",
    r"^【真实性核查报告】",
    r"^【.*核查报告】",
]

# 整段删除（标题及其下面整段，直到下一标题）
BLOCK_DELETE_HEADERS = [
    r"真实性核查报告",
    r"【.*核查报告】",
    r"信源类型/国家分布",
    r"验证方法/通过率",
    r"特别说明",
]

# 行内清理
BULLET_PREFIX_RE = re.compile(r"^[·•・]\s*")
MD_BOLD_RE = re.compile(r"\*\*([^*\n]+?)\*\*")
EDITORIAL_NOTE_RE = re.compile(r"／注：[^／\n]*")
TIMESTAMP_TAG_RE = re.compile(r"\s*［2026-\d{2}-\d{2}\s*已验证\s*status[^］]*］")


def should_delete_para(text):
    """判断段落是否整段删除。"""
    if not text.strip():
        return False
    for pat in LINE_DELETE_PATTERNS:
        if re.search(pat, text):
            return True
    # markdown 分隔线
    if re.match(r"^-{3,}$|^={3,}$", text.strip()):
        return True
    return False


def clean_text(text):
    """段落内文本清洗。"""
    # 去段首项目符号
    text = BULLET_PREFIX_RE.sub("", text)
    # 去 markdown 粗体（保留文字）
    text = MD_BOLD_RE.sub(r"\1", text)
    # 去编辑批注
    text = EDITORIAL_NOTE_RE.sub("", text)
    # 去时间戳验证标签
    text = TIMESTAMP_TAG_RE.sub("", text)
    return text


def is_block_delete_header(text):
    for pat in BLOCK_DELETE_HEADERS:
        if re.search(pat, text):
            return True
    return False


def is_chapter_title(text):
    return bool(re.match(r"^第[一二三四五六七八九十]+章", text.strip()))


def is_appendix(text):
    return bool(re.match(r"^(参考文献|附录|附件)", text.strip()))


def fix_paragraph_format(p, is_appendix_para=False):
    """修复段落格式。"""
    if is_appendix_para:
        return
    pf = p.paragraph_format
    if pf.left_indent is not None:
        pf.left_indent = None
    if pf.first_line_indent != TARGET_INDENT:
        pf.first_line_indent = TARGET_INDENT
    # 清 numPr
    pPr = p._p.find(f"{WORDML_NS}pPr")
    if pPr is not None:
        numPr = pPr.find(f"{WORDML_NS}numPr")
        if numPr is not None:
            pPr.remove(numPr)


def process_doc(path):
    """处理一个 docx 文件。"""
    doc = Document(path)
    body = doc.element.body
    paras = list(doc.paragraphs)

    # 阶段 1: 标记要删除的段落
    delete_indices = set()
    in_block_delete = False
    in_appendix = False

    for i, p in enumerate(paras):
        t = p.text.strip()
        if not t:
            continue
        if is_appendix(t):
            in_appendix = True
            in_block_delete = False
            continue
        if in_appendix:
            continue
        # 工具元数据区段
        if is_block_delete_header(t):
            in_block_delete = True
            delete_indices.add(i)
            continue
        if in_block_delete:
            # 遇到下一个章节标题/正常二级标题/附录则退出
            if is_chapter_title(t) or is_appendix(t) or re.match(r"^[一二三四五六]、", t):
                in_block_delete = False
                # 不删除这一段
            else:
                delete_indices.add(i)
                continue
        # 行级删除
        if should_delete_para(t):
            delete_indices.add(i)

    # 阶段 2: 删除段落（从后往前）
    for i in sorted(delete_indices, reverse=True):
        p_element = paras[i]._element
        p_element.getparent().remove(p_element)

    # 阶段 3: 重新读取段落，进行文本清洗和格式修复
    paras = list(doc.paragraphs)
    in_appendix = False
    for p in paras:
        t = p.text.strip()
        if not t:
            continue
        if is_appendix(t):
            in_appendix = True
            continue
        if in_appendix:
            continue
        if is_chapter_title(t):
            continue
        # 文本清洗
        for run in p.runs:
            if run.text:
                new_text = clean_text(run.text)
                if new_text != run.text:
                    run.text = new_text
        # 格式修复
        fix_paragraph_format(p, is_appendix_para=False)

    doc.save(path)
    return len(delete_indices)


def collect_files(paths):
    files = []
    for path in paths:
        if os.path.isdir(path):
            files.extend(sorted(
                glob.glob(os.path.join(path, "**", "*.docx"), recursive=True)))
        elif os.path.isfile(path) and path.endswith(".docx"):
            files.append(path)
    return files


def main():
    if len(sys.argv) < 2:
        print(__doc__)
        sys.exit(1)
    files = collect_files(sys.argv[1:])
    print(f"\n🔧 报告清洗器 - 共 {len(files)} 个文件\n" + "=" * 60)
    for f in files:
        try:
            n = process_doc(f)
            print(f"  ✅ {os.path.basename(f)} - 删除 {n} 段")
        except Exception as e:
            print(f"  ❌ {os.path.basename(f)} - 错误: {e}")
    print("\n完成")


if __name__ == "__main__":
    main()
