#!/usr/bin/env python3
"""
Word 导出脚本 - word-exporter skill
支持完整 Markdown 格式：标题、段落、加粗、斜体、行内代码、代码块、
有序/无序列表（含嵌套）、表格、水平线。

用法: python3 export_word.py --title "标题" --content "内容" --output "输出路径"
"""
import sys
import os
import re
import argparse

sys.path.insert(0, '/workspace/.local/lib/python3.11/site-packages')

from docx import Document
from docx.shared import Pt, RGBColor, Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docx.oxml import OxmlElement


# ─────────────────────────────────────────────────────────────────────────────
# Inline formatting helpers
# ─────────────────────────────────────────────────────────────────────────────

def apply_inline(run, text, bold=False, italic=False, code=False):
    run.text = text
    if bold:
        run.bold = True
    if italic:
        run.italic = True
    if code:
        run.font.name = 'Courier New'
        run.font.size = Pt(10)
        run.font.color.rgb = RGBColor(0xC7, 0x25, 0x4E)


def add_inline_text(paragraph, text):
    """Parse inline markdown (**bold**, *italic*, `code`, ***bold-italic***) and add runs."""
    # Pattern order matters: bold-italic first, then bold, then italic, then code
    pattern = re.compile(
        r'(\*\*\*(.+?)\*\*\*)'   # bold-italic
        r'|(\*\*(.+?)\*\*)'       # bold
        r'|(__(.+?)__)'            # bold (alt)
        r'|(\*(.+?)\*)'            # italic
        r'|(_(.+?)_)'              # italic (alt)
        r'|(`(.+?)`)',             # inline code
        re.DOTALL
    )
    pos = 0
    for m in pattern.finditer(text):
        # Plain text before match
        if m.start() > pos:
            paragraph.add_run(text[pos:m.start()])
        if m.group(1):   # bold-italic
            apply_inline(paragraph.add_run(), m.group(2), bold=True, italic=True)
        elif m.group(3): # bold **
            apply_inline(paragraph.add_run(), m.group(4), bold=True)
        elif m.group(5): # bold __
            apply_inline(paragraph.add_run(), m.group(6), bold=True)
        elif m.group(7): # italic *
            apply_inline(paragraph.add_run(), m.group(8), italic=True)
        elif m.group(9): # italic _
            apply_inline(paragraph.add_run(), m.group(10), italic=True)
        elif m.group(11): # inline code
            apply_inline(paragraph.add_run(), m.group(12), code=True)
        pos = m.end()
    # Remaining plain text
    if pos < len(text):
        paragraph.add_run(text[pos:])


# ─────────────────────────────────────────────────────────────────────────────
# Table helpers
# ─────────────────────────────────────────────────────────────────────────────

def is_table_separator(line):
    """Check if line is a markdown table separator like |---|---|"""
    stripped = line.strip()
    if not stripped.startswith('|'):
        return False
    return bool(re.match(r'^[\|\s\-:]+$', stripped))


def parse_table_row(line):
    """Parse a markdown table row into a list of cell strings."""
    line = line.strip()
    if line.startswith('|'):
        line = line[1:]
    if line.endswith('|'):
        line = line[:-1]
    return [cell.strip() for cell in line.split('|')]


def add_table(doc, rows):
    """Add a Word table from a list of row-lists."""
    if not rows:
        return
    col_count = max(len(r) for r in rows)
    table = doc.add_table(rows=len(rows), cols=col_count)
    table.style = 'Table Grid'
    for i, row_data in enumerate(rows):
        for j, cell_text in enumerate(row_data):
            if j < col_count:
                cell = table.cell(i, j)
                p = cell.paragraphs[0]
                add_inline_text(p, cell_text)
                if i == 0:  # header row bold
                    for run in p.runs:
                        run.bold = True
    doc.add_paragraph('')  # spacing after table


# ─────────────────────────────────────────────────────────────────────────────
# Horizontal rule
# ─────────────────────────────────────────────────────────────────────────────

def add_horizontal_rule(doc):
    p = doc.add_paragraph()
    pPr = p._p.get_or_add_pPr()
    pBdr = OxmlElement('w:pBdr')
    bottom = OxmlElement('w:bottom')
    bottom.set(qn('w:val'), 'single')
    bottom.set(qn('w:sz'), '6')
    bottom.set(qn('w:space'), '1')
    bottom.set(qn('w:color'), 'AAAAAA')
    pBdr.append(bottom)
    pPr.append(pBdr)


# ─────────────────────────────────────────────────────────────────────────────
# Main export function
# ─────────────────────────────────────────────────────────────────────────────

def export_word(title: str, content: str, output_path: str) -> str:
    doc = Document()

    # Document title
    heading = doc.add_heading(title, level=0)
    heading.alignment = WD_ALIGN_PARAGRAPH.CENTER

    lines = content.split('\n')
    i = 0
    while i < len(lines):
        line = lines[i]
        raw = line.rstrip()

        # ── Fenced code block ────────────────────────────────────────────────
        if raw.startswith('```'):
            lang = raw[3:].strip()
            code_lines = []
            i += 1
            while i < len(lines) and not lines[i].rstrip().startswith('```'):
                code_lines.append(lines[i].rstrip('\n'))
                i += 1
            p = doc.add_paragraph()
            run = p.add_run('\n'.join(code_lines))
            run.font.name = 'Courier New'
            run.font.size = Pt(9)
            # Light grey shading
            pPr = p._p.get_or_add_pPr()
            shd = OxmlElement('w:shd')
            shd.set(qn('w:val'), 'clear')
            shd.set(qn('w:color'), 'auto')
            shd.set(qn('w:fill'), 'F5F5F5')
            pPr.append(shd)
            i += 1
            continue

        # ── Horizontal rule ──────────────────────────────────────────────────
        if re.match(r'^(\-{3,}|\*{3,}|_{3,})\s*$', raw):
            add_horizontal_rule(doc)
            i += 1
            continue

        # ── Headings ─────────────────────────────────────────────────────────
        m = re.match(r'^(#{1,6})\s+(.*)', raw)
        if m:
            level = min(len(m.group(1)), 6)
            doc.add_heading(m.group(2).strip(), level=level)
            i += 1
            continue

        # ── Table ────────────────────────────────────────────────────────────
        if raw.startswith('|') and '|' in raw[1:]:
            table_rows = []
            while i < len(lines) and lines[i].strip().startswith('|'):
                if not is_table_separator(lines[i]):
                    table_rows.append(parse_table_row(lines[i]))
                i += 1
            add_table(doc, table_rows)
            continue

        # ── Unordered list ───────────────────────────────────────────────────
        m = re.match(r'^(\s*)([-*+])\s+(.*)', raw)
        if m:
            indent = len(m.group(1))
            level = indent // 2  # 0 = top, 1 = nested, etc.
            style = 'List Bullet 2' if level > 0 else 'List Bullet'
            p = doc.add_paragraph(style=style)
            add_inline_text(p, m.group(3))
            i += 1
            continue

        # ── Ordered list ─────────────────────────────────────────────────────
        m = re.match(r'^(\s*)\d+[.)]\s+(.*)', raw)
        if m:
            indent = len(m.group(1))
            style = 'List Number 2' if indent > 0 else 'List Number'
            p = doc.add_paragraph(style=style)
            add_inline_text(p, m.group(2))
            i += 1
            continue

        # ── Blockquote ───────────────────────────────────────────────────────
        if raw.startswith('> '):
            p = doc.add_paragraph(style='Quote')
            add_inline_text(p, raw[2:])
            i += 1
            continue

        # ── Empty line ───────────────────────────────────────────────────────
        if raw.strip() == '':
            doc.add_paragraph('')
            i += 1
            continue

        # ── Normal paragraph ─────────────────────────────────────────────────
        p = doc.add_paragraph()
        add_inline_text(p, raw)
        i += 1

    os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)

    # Footer signature
    doc.add_paragraph('')
    p = doc.add_paragraph()
    p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = p.add_run('以上内容由 ECclaw 生成')
    run.font.color.rgb = RGBColor(0xAA, 0xAA, 0xAA)
    run.font.size = Pt(9)

    doc.save(output_path)
    return output_path


# ─────────────────────────────────────────────────────────────────────────────
# CLI
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='导出 Word 文档（支持完整 Markdown）')
    parser.add_argument('--title',   required=True, help='文档标题')
    parser.add_argument('--content', required=True, help='文档正文（Markdown 格式）')
    parser.add_argument('--output',  required=True, help='输出 .docx 文件路径')
    args = parser.parse_args()

    output = export_word(args.title, args.content, args.output)
    print(f'output_path: {output}')
    print('Word 文档导出成功')
