#!/usr/bin/env python3
"""
事件参阅报告 Word 文档生成器
按公文排版规范生成符合格式要求的 Word 文档
"""

import argparse
import os
import re
import sys
from pathlib import Path

try:
    from docx import Document
    from docx.shared import Pt, Cm, Inches, Emu
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    from docx.enum.section import WD_ORIENT
    from docx.oxml.ns import qn, nsdecls
    from docx.oxml import parse_xml
except ImportError:
    print("ERROR: python-docx not installed. Run: pip install python-docx", file=sys.stderr)
    sys.exit(1)

# ── 公文排版参数 ──
MARGIN_TOP = Cm(3.7)
MARGIN_BOTTOM = Cm(2.8)
MARGIN_LEFT = Cm(2.8)
MARGIN_RIGHT = Cm(2.6)

FONT_TITLE = '宋体'
FONT_TITLE_FALLBACK = '宋体'
FONT_HEITI = '黑体'
FONT_KAITI = '楷体'
FONT_FANGSONG = '仿宋'
FONT_FANGSONG_FALLBACK = '仿宋'

SIZE_TITLE = Pt(22)    # 二号 ≈ 22pt
SIZE_SANHAO = Pt(16)   # 三号 ≈ 16pt
SIZE_XIAOSI = Pt(12)   # 小四号 ≈ 12pt

LINE_SPACING = Pt(28)  # 固定值 28 磅

IMAGE_WIDTH = Cm(6)
IMAGE_HEIGHT = Cm(4.5)


def setup_page(doc):
    """设置页面参数：A4、页边距"""
    section = doc.sections[0]
    section.page_width = Cm(21.0)
    section.page_height = Cm(29.7)
    section.orientation = WD_ORIENT.PORTRAIT
    section.top_margin = MARGIN_TOP
    section.bottom_margin = MARGIN_BOTTOM
    section.left_margin = MARGIN_LEFT
    section.right_margin = MARGIN_RIGHT


def set_paragraph_format(paragraph, font_name, font_size, bold=False, alignment=None,
                         first_line_indent=None, line_spacing=LINE_SPACING):
    """设置段落格式"""
    fmt = paragraph.paragraph_format
    fmt.line_spacing = line_spacing
    fmt.space_before = Pt(0)
    fmt.space_after = Pt(0)
    if alignment is not None:
        fmt.alignment = alignment
    if first_line_indent is not None:
        fmt.first_line_indent = first_line_indent

    for run in paragraph.runs:
        run.font.size = font_size
        run.font.bold = bold
        run.font.name = font_name
        # 设置中文字体
        run._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)


def add_title(doc, text):
    """添加标题（方正小标宋简体 二号 居中）"""
    # 空两行
    for _ in range(2):
        p = doc.add_paragraph()
        set_paragraph_format(p, FONT_FANGSONG, SIZE_SANHAO, line_spacing=LINE_SPACING)

    p = doc.add_paragraph(text)
    set_paragraph_format(p, FONT_TITLE, SIZE_TITLE, bold=False,
                         alignment=WD_ALIGN_PARAGRAPH.CENTER, line_spacing=LINE_SPACING)
    # 回退字体
    for run in p.runs:
        run.font.name = FONT_TITLE
        run._element.rPr.rFonts.set(qn('w:eastAsia'), FONT_TITLE)

    # 标题后空一行
    p2 = doc.add_paragraph()
    set_paragraph_format(p2, FONT_FANGSONG, SIZE_SANHAO, line_spacing=LINE_SPACING)


def add_heading_level1(doc, text):
    """添加一级标题（黑体 三号）"""
    p = doc.add_paragraph(text)
    set_paragraph_format(p, FONT_HEITI, SIZE_SANHAO, bold=True, line_spacing=LINE_SPACING)
    for run in p.runs:
        run.font.name = FONT_HEITI
        run._element.rPr.rFonts.set(qn('w:eastAsia'), FONT_HEITI)


def add_heading_level2(doc, text):
    """添加二级标题（楷体_GB2312 三号）"""
    p = doc.add_paragraph(text)
    set_paragraph_format(p, FONT_KAITI, SIZE_SANHAO, bold=True, line_spacing=LINE_SPACING)
    for run in p.runs:
        run.font.name = FONT_KAITI
        run._element.rPr.rFonts.set(qn('w:eastAsia'), FONT_KAITI)


def add_body_text(doc, text, indent=True):
    """添加正文（仿宋_GB2312 三号 首行缩进两字）"""
    p = doc.add_paragraph(text)
    first_indent = Cm(0.74) if indent else None  # 约两个三号字宽度
    set_paragraph_format(p, FONT_FANGSONG, SIZE_SANHAO,
                         first_line_indent=first_indent, line_spacing=LINE_SPACING)
    for run in p.runs:
        run.font.name = FONT_FANGSONG
        run._element.rPr.rFonts.set(qn('w:eastAsia'), FONT_FANGSONG)
    return p


def add_image_right(doc, image_path):
    """添加图片（6cm×4.5cm，四周环绕，居右）"""
    if not os.path.exists(image_path):
        print(f"WARNING: Image not found: {image_path}", file=sys.stderr)
        return

    p = doc.add_paragraph()
    p.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    p.paragraph_format.line_spacing = LINE_SPACING

    run = p.add_run()
    run.add_picture(image_path, width=IMAGE_WIDTH, height=IMAGE_HEIGHT)

    # 设置四周环绕型
    inline = run._element.findall(qn('wp:inline'))
    if inline:
        inline_elem = inline[0]
        # 将 inline 转换为 anchor（四周环绕）
        anchor = parse_xml(
            f'<wp:anchor {nsdecls("wp")} '
            f'distT="0" distB="0" distL="0" distR="0" '
            f'simplePos="0" relativeHeight="0" behindDoc="0" '
            f'locked="0" layoutInCell="1" allowOverlap="1">'
            f'<wp:simplePos x="0" y="0"/>'
            f'<wp:positionH relativeFrom="column">'
            f'<wp:align>right</wp:align>'
            f'</wp:positionH>'
            f'<wp:positionV relativeFrom="paragraph">'
            f'<wp:posOffset>0</wp:posOffset>'
            f'</wp:positionV>'
            f'<wp:extent cx="{int(IMAGE_WIDTH.emu)}" cy="{int(IMAGE_HEIGHT.emu)}"/>'
            f'<wp:effectExtent l="0" t="0" r="0" b="0"/>'
            f'<wp:wrapSquare wrapText="bothSides"/>'
            f'<wp:docPr id="1" name="Picture 1"/>'
            f'</wp:anchor>'
        )
        inline_elem.addprevious(anchor)
        inline_elem.getparent().remove(inline_elem)


def parse_markdown_content(md_text):
    """解析 Markdown 内容为结构化段落列表"""
    sections = []
    current_section = None
    current_content = []

    for line in md_text.split('\n'):
        stripped = line.strip()

        # 检测一级标题
        if stripped.startswith('# ') and not stripped.startswith('## '):
            if current_section is not None:
                sections.append({
                    'type': 'heading1',
                    'text': current_section,
                    'content': '\n'.join(current_content)
                })
            current_section = stripped[2:]
            current_content = []
        # 检测二级标题
        elif stripped.startswith('## '):
            if current_section is not None:
                sections.append({
                    'type': 'heading1',
                    'text': current_section,
                    'content': '\n'.join(current_content)
                })
            current_section = stripped[3:]
            current_content = []
        # 检测三级标题
        elif stripped.startswith('### '):
            current_content.append(f'__SUBHEAD__:{stripped[4:]}')
        else:
            current_content.append(line)

    if current_section is not None:
        sections.append({
            'type': 'heading1',
            'text': current_section,
            'content': '\n'.join(current_content)
        })
    elif current_content:
        # 无标题时，将全部内容作为一个无名section
        sections.append({
            'type': 'body',
            'text': '',
            'content': '\n'.join(current_content)
        })

    return sections


def generate_report(title, date, input_file, output_file, images=None):
    """生成 Word 报告"""
    doc = Document()
    setup_page(doc)

    # 读取素材
    if os.path.exists(input_file):
        with open(input_file, 'r', encoding='utf-8') as f:
            content = f.read()
    else:
        print(f"WARNING: Input file not found: {input_file}, generating template", file=sys.stderr)
        content = ""

    # 标题
    add_title(doc, title)

    # 解析并写入内容
    if content.strip():
        sections = parse_markdown_content(content)
        for sec in sections:
            # 不再添加一级标题，正文直接按三段连续排布
            paragraphs = sec['content'].split('\n\n')
            for para_text in paragraphs:
                para_text = para_text.strip()
                if not para_text:
                    continue
                # 处理子标题
                if para_text.startswith('__SUBHEAD__:'):
                    add_heading_level2(doc, para_text.replace('__SUBHEAD__:', ''))
                else:
                    # 清理 Markdown 标记
                    clean = re.sub(r'\*\*(.+?)\*\*', r'\1', para_text)
                    clean = re.sub(r'\[(.+?)\]\(.+?\)', r'\1', clean)
                    clean = clean.replace('①', '①').replace('②', '②').replace('③', '③')
                    add_body_text(doc, clean)
    else:
        # 生成模板
        # 不再添加一级标题，正文直接按三段连续排布
        add_body_text(doc, '【信息来源】[媒体名称] [日期] 报道称……')
        add_body_text(doc, '【核心事件】事件综合概述……')
        add_body_text(doc, '【关键错误表述】摘录原文言论……')

        add_body_text(doc, '【深层动机】点明战略考量……')

        add_heading_level2(doc, '（一）定性批判与多层危害分析')
        add_body_text(doc, '【原则定性】……')
        add_body_text(doc, '【现实危害】……')
        add_body_text(doc, '【局势影响】……')
        add_body_text(doc, '【行为趋势】……')

        add_heading_level2(doc, '（二）对策建议')
        add_body_text(doc, '【舆论应对】……')
        add_body_text(doc, '【外交应对】……')
        add_body_text(doc, '【内控防范】……')
        add_body_text(doc, '【长期布局】……')

    # 插入图片
    if images:
        for img_path in images:
            add_image_right(doc, img_path)

    # 确保输出目录存在
    os.makedirs(os.path.dirname(output_file) or '.', exist_ok=True)

    # 保存
    doc.save(output_file)
    print(f"✅ Report generated: {output_file}")


def main():
    parser = argparse.ArgumentParser(description='事件参阅报告 Word 文档生成器')
    parser.add_argument('--title', required=True, help='报告标题')
    parser.add_argument('--date', required=True, help='报告日期 (YYYY-MM-DD)')
    parser.add_argument('--input', required=True, help='Markdown 素材文件路径')
    parser.add_argument('--output', required=True, help='Word 文档输出路径')
    parser.add_argument('--images', nargs='*', default=None, help='图片文件路径列表')
    args = parser.parse_args()

    generate_report(args.title, args.date, args.input, args.output, args.images)


if __name__ == '__main__':
    main()
