#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""把 MD 里带 <!-- deck:rebuild-table --> 标记的表格写回 deck 布局模型。

流程（MD 是唯一数据源，版式仍取自 PPTX 模型）：
    deck_md_apply.py <layout_model.json> <in.md> <out_model.json>
    gen_q3_deck.py   <out_model.json> <out.html> [xls.json]

规则
- 只处理带标记的表；没标记的页面/表格一律不动（防止误伤其它 12 页）
- 行首只有一个非空单元格 → 当成标题行，横跨整表（加粗、居中）
- SPEC[页][header_rows] 列出的行 → 表头（填充色 + 居中 + 加粗）
- 其余 → 数据单元格（居中）
"""
import io, re, sys, json

LAY, MD, OUT = sys.argv[1], sys.argv[2], sys.argv[3]

# 每页重建规格：header_rows = Markdown 行号(从0起，标题行会自动识别，不必列)
SPEC = {
    3: {'header_rows': [1], 'hdr_fill': 'B6C7EA', 'sz': 10.0, 'hdr_sz': 10.0, 'title_sz': 15.0,
        # 年度目标 / 实际完成 / 年度完成率 / 销售年度 + 12个月 + 年度累计 + 同比
        'col_w': [7.0, 7.0, 7.0, 7.0] + [4.5] * 12 + [10.0, 8.0]},
    7: {'header_rows': [0], 'hdr_fill': None, 'sz': 11.0, 'hdr_sz': 11.0, 'title_sz': 15.0,
        # 产品品类 + 12个月 + 合计
        'col_w': [16.0] + [6.2] * 12 + [9.6]},
}


def cell(t, sz=11.0, b=False, al='CENTER', fill=None, span_w=1, span_h=1,
         origin=False, spanned=False):
    return {
        'runs': ([{'t': t, 'sz': sz, 'b': b, 'i': False, 'c': '000000', 'sc': None,
                   'f': '宋体'}] if t else []),
        'al': al if t else None,
        'anchor': 'MIDDLE' if t else None,
        't': t,
        'span_w': span_w, 'span_h': span_h,
        'origin': origin, 'spanned': spanned,
        'fill': fill,
    }


def parse_md(path):
    """{页码: [[md_row, ...], ...]} —— 每页把带标记的表按出现顺序收集"""
    txt = io.open(path, encoding='utf-8').read()
    out = {}
    parts = re.split(r'^## P(\d+) · ', txt, flags=re.M)
    for i in range(1, len(parts) - 1, 2):
        page, body = int(parts[i]), parts[i + 1]
        tabs = []
        for m in re.finditer(r'<!--\s*deck:rebuild-table\s*-->\s*\n((?:\|.*\n)+)', body):
            rows = []
            for line in m.group(1).strip().split('\n'):
                if re.match(r'^\|[\s\-:|]+\|$', line):      # 分隔行
                    continue
                rows.append([c.strip() for c in line.strip().strip('|').split('|')])
            if rows:
                tabs.append(rows)
        if tabs:
            out[page] = tabs
    return out


def build_grid(md_rows, spec):
    ncol = max(len(r) for r in md_rows)
    grid = []
    for ri, row in enumerate(md_rows):
        row = list(row) + [''] * (ncol - len(row))
        ne = [c for c in row if c != '']
        if ri == 0 and len(ne) == 1:                       # 标题行：横跨整表
            cells = [cell(ne[0], sz=spec['title_sz'], b=True, origin=True, span_w=ncol)]
            cells += [cell('', spanned=True) for _ in range(ncol - 1)]
        else:
            is_hdr = ri in spec['header_rows']
            cells = [cell(t,
                          sz=spec['hdr_sz'] if is_hdr else spec['sz'],
                          b=is_hdr,
                          fill=spec['hdr_fill'] if is_hdr else None)
                     for t in row]
        grid.append(cells)
    return grid


def main():
    model = json.load(io.open(LAY, encoding='utf-8'))
    mdtabs = parse_md(MD)
    if not mdtabs:
        print('❌ MD 里没有找到 <!-- deck:rebuild-table --> 标记的表'); sys.exit(1)

    print('MD 待重建表格：%s' % {k: len(v) for k, v in mdtabs.items()})
    log = []
    for page, tables in sorted(mdtabs.items()):
        sl = [s for s in model['slides'] if s['n'] == page]
        if not sl:
            log.append('  ⚠️ P%d 模型里没有这页 → 跳过' % page); continue
        sl = sl[0]
        tbs = [sh for sh in sl['shapes'] if sh['kind'] == 'table']
        for ti, md_rows in enumerate(tables):
            if ti >= len(tbs):
                log.append('  ⚠️ P%d 第%d个表 MD 有、模型没有 → 跳过' % (page, ti)); continue
            sh = tbs[ti]
            spec = SPEC.get(page, {'header_rows': [0], 'hdr_fill': None,
                                   'sz': 11.0, 'hdr_sz': 11.0, 'title_sz': 15.0})
            grid = build_grid(md_rows, spec)
            ncol = len(grid[0])
            cw = spec.get('col_w')
            if not cw or len(cw) != ncol:
                cw = [100.0 / ncol] * ncol
            old = '%d行×%d列' % (sh.get('rows', 0), sh.get('cols', 0))
            sh['grid'], sh['rows'], sh['cols'], sh['col_w'] = grid, len(grid), ncol, cw
            log.append('  P%-2d 表%d  %s  →  %d行×%d列' % (page, ti, old, len(grid), ncol))
    for x in log:
        print(x)
    json.dump(model, io.open(OUT, 'w', encoding='utf-8'), ensure_ascii=False)
    print('✅ 已写出 %s' % OUT)


main()
