"""Render the reviewed Markdown into the retained CPT Word template.

Run with the bundled workspace Python. Source content remains Markdown;
research payloads and binary outputs stay in ignored outputs/.
"""
from pathlib import Path
import re
import zipfile
import argparse
from docx import Document
from docx.shared import Pt, RGBColor, Cm
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPE

ROOT = Path(__file__).resolve().parents[2]
BASE = ROOT / 'outputs/presales-ticket-flow-20260920'
parser = argparse.ArgumentParser()
parser.add_argument('--source', type=Path, default=Path(__file__).with_name('项目工单支持流程.md'))
parser.add_argument('--output', type=Path, default=BASE / '项目工单支持流程_V0.1评审稿.docx')
args = parser.parse_args()
SOURCE = args.source
OUT = args.output
OUT.parent.mkdir(parents=True, exist_ok=True)
doc = Document(BASE / 'template/starter.docx')

for name, size, color in [('Normal', 11, '222222'), ('Title', 23, '000000'),
                           ('Heading 1', 15, '153D51'), ('Heading 2', 12, '153D51')]:
    st = doc.styles[name] if name in doc.styles else doc.styles.add_style(name, WD_STYLE_TYPE.PARAGRAPH)
    if name != 'Normal': st.base_style = doc.styles['Normal']
    st.font.name = 'Arial'
    st.font.size = Pt(size)
    st.font.color.rgb = RGBColor.from_string(color)
    st.element.get_or_add_rPr().rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei')
    st.paragraph_format.space_after = Pt(6)
    st.paragraph_format.widow_control = True
    st.paragraph_format.line_spacing = Pt(size * 1.5)
    snap = OxmlElement('w:snapToGrid'); snap.set(qn('w:val'), '0')
    st.element.get_or_add_pPr().append(snap)
    if name.startswith('Heading'):
        st.paragraph_format.space_before = Pt(14)
        st.paragraph_format.keep_with_next = True
    if name == 'Title':
        st.paragraph_format.space_after = Pt(12)
        st.paragraph_format.keep_with_next = True

def add_text(p, text):
    # Retain Markdown emphasis and readable link captions; URLs remain copyable.
    text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\1（\2）', text)
    for i, part in enumerate(re.split(r'\*\*(.*?)\*\*', text)):
        r = p.add_run(part)
        r.bold = bool(i % 2)
        r._element.get_or_add_rPr().get_or_add_rFonts().set(qn('w:eastAsia'), 'Heiti SC')

def table(lines):
    parsed = [[s.strip() for s in line.strip().strip('|').split('|')] for line in lines]
    parsed = [r for r in parsed if not all(re.fullmatch(r'[:\-\s]+', c) for c in r)]
    n = len(parsed[0]);t = doc.add_table(rows=0, cols=n)
    t.autofit = False
    width = 14.65
    ratios = {2:[.27,.73],3:[.24,.38,.38],4:[.23,.15,.37,.25]}.get(n,[1/n]*n)
    if parsed[0][0] == 'Use Case ID': ratios = [.18,.28,.24,.30]
    if parsed[0][0] == '优先级': ratios = [.13,.30,.24,.33]
    if parsed[0] == ['字段', '控件', '设置']: ratios = [.25,.16,.59]
    if parsed[0][0].startswith('条件命中的选项'): ratios = [.70,.30]
    for col,rat in zip(t.columns,ratios):col.width=Cm(width*rat)
    pr = t._tbl.tblPr
    borders = OxmlElement('w:tblBorders')
    for edge in ['top','left','bottom','right','insideH','insideV']:
        x=OxmlElement('w:'+edge);x.set(qn('w:val'),'single');x.set(qn('w:sz'),'4');x.set(qn('w:color'),'D4DDE2');borders.append(x)
    pr.append(borders)
    for idx,row in enumerate(parsed):
        cells=t.add_row().cells
        rpr=t.rows[-1]._tr.get_or_add_trPr()
        rpr.append(OxmlElement('w:cantSplit'))
        if idx==0:rpr.append(OxmlElement('w:tblHeader'))
        for cell,txt,ratio in zip(cells,row,ratios):
            cell.width=Cm(width*ratio)
            cp=cell._tc.get_or_add_tcPr()
            margins=OxmlElement('w:tcMar')
            for edge,val in [('top','75'),('bottom','75'),('left','85'),('right','85')]:
                v=OxmlElement('w:'+edge);v.set(qn('w:w'),val);v.set(qn('w:type'),'dxa');margins.append(v)
            cp.append(margins)
            if idx==0:
                sh=OxmlElement('w:shd');sh.set(qn('w:fill'),'EAF0F3');cp.append(sh)
            p=cell.paragraphs[0];p.paragraph_format.space_after=Pt(1);p.paragraph_format.line_spacing=Pt(14)
            add_text(p,txt)
            for r in p.runs:r.font.size=Pt(10.5);r.bold = idx==0 or r.bold
    doc.add_paragraph().paragraph_format.space_after=Pt(1)

lines=SOURCE.read_text().splitlines();i=0
while i<len(lines):
    line=lines[i].strip()
    if not line:i+=1;continue
    if line.startswith('|'):
        buf=[]
        while i<len(lines) and lines[i].strip().startswith('|'):buf.append(lines[i]);i+=1
        table(buf);continue
    if line.startswith('# '):
        p=doc.add_paragraph(style='Title');add_text(p,line[2:])
    elif line.startswith('## '):
        p=doc.add_paragraph(style='Heading 1');add_text(p,line[3:])
        if SOURCE.name == '企业微信后台配置操作说明.md' and line.startswith('## 3 '):
            p.paragraph_format.page_break_before = True
    elif line.startswith('### '):
        p=doc.add_paragraph(style='Heading 2');add_text(p,line[4:])
    else:
        p=doc.add_paragraph();add_text(p,line[2:] if line.startswith('- ') else line)
        if line.startswith('- '):p.paragraph_format.left_indent=Cm(.3)
    i+=1

footer=doc.sections[0].footer.paragraphs[0]
footer.alignment=2
r=footer.add_run('内部评审稿  ·  ');r.font.size=Pt(9)
field=OxmlElement('w:fldSimple');field.set(qn('w:instr'),'PAGE');footer._p.append(field)

tmp=BASE/'working.docx';doc.save(tmp)
# Transplant only body, body styles and the intentionally added footer;
# all opaque/header/template parts remain byte-identical to the starter.
with zipfile.ZipFile(BASE/'template/starter.docx') as src,zipfile.ZipFile(tmp) as generated,zipfile.ZipFile(OUT,'w',zipfile.ZIP_DEFLATED) as dest:
    changed={'word/document.xml','word/styles.xml','word/footer1.xml'}
    for entry in src.infolist():
        dest.writestr(entry,generated.read(entry.filename) if entry.filename in changed else src.read(entry.filename))
print(OUT)
