#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""整节做字符级对齐（先拼平再切回段落），重建左右对比页。
左=上一版定稿（只读，删除处标红删除线）；右=新版（可改，新增处标绿）。"""
import re, os, json, difflib, html, time, shutil

BASE = '/root/media-hub/export/拍摄'
PAGE = os.path.join(BASE, 'compare-v7-edit.html')
LIVE = '/root/media-hub/export/v7-live.md'
HTMLS = '/root/media-hub/export/v7-live-html.json'
OLD = '/tmp/old_snapshot.md'
NEW = '/tmp/new.md'

HEADS_RE = re.compile(r'^【\s*(\d+)\s*[.．、]\s*(.*?)】\s*$', re.M)


def han(s):
    return len(re.findall(r'[\u4e00-\u9fff]', s))


def load(path):
    t = open(path, encoding='utf-8').read()
    parts = HEADS_RE.split(t)
    d = {}
    for i in range(1, len(parts) - 2, 3):
        n = int(parts[i])
        title = parts[i + 1].strip()
        paras = [ln.strip() for ln in parts[i + 2].split('\n') if ln.strip()]
        d[n] = (title, paras)
    return d


def esc(s):
    return html.escape(s, quote=False)


def render(flat, flags, bounds):
    """按段落切回 html；flags 逐字 'del'/'ins'/''"""
    out = []
    for k in range(len(bounds) - 1):
        s, e = bounds[k], bounds[k + 1]
        # 先切出连续同标记的片段，纯空白的片段不标色（拆段带出来的空格，不是真改动）
        runs, cur = [], None
        for idx in range(s, e):
            f = flags[idx]
            if f != cur:
                runs.append([f, []])
                cur = f
            runs[-1][1].append(flat[idx])
        buf = []
        for f, chars in runs:
            t = ''.join(chars)
            if f and t.strip():
                buf.append('<%s>%s</%s>' % (f, esc(t), f))
            else:
                buf.append(esc(t))
        out.append(''.join(buf))
    return out


def diff_section(op, np_):
    old_flat = ''.join(op)
    new_flat = ''.join(np_)
    ob, nb = [0], [0]
    for p in op:
        ob.append(ob[-1] + len(p))
    for p in np_:
        nb.append(nb[-1] + len(p))
    fo = [''] * len(old_flat)
    fn = [''] * len(new_flat)
    sm = difflib.SequenceMatcher(None, old_flat, new_flat, autojunk=False)
    for tag, i1, i2, j1, j2 in sm.get_opcodes():
        if tag == 'equal':
            continue
        if tag in ('delete', 'replace'):
            for i in range(i1, i2):
                fo[i] = 'del'
        if tag in ('insert', 'replace'):
            for j in range(j1, j2):
                fn[j] = 'ins'
    left = render(old_flat, fo, ob)
    right = render(new_flat, fn, nb)
    ins_runs = len(re.findall(r'<ins>', ''.join(right)))
    del_runs = len(re.findall(r'<del>', ''.join(left)))
    return left, right, ins_runs, del_runs


def build():
    OLD_S, NEW_S = load(OLD), load(NEW)
    secs, to, tn = [], 0, 0
    for n in range(1, 16):
        ot, op = OLD_S[n]
        nt, np_ = NEW_S[n]
        left, right, ins_runs, del_runs = diff_section(op, np_)
        ho = sum(han(p) for p in op)
        hn = sum(han(p) for p in np_)
        to += ho; tn += hn
        secs.append(dict(n=n, ot=ot, nt=nt, ho=ho, hn=hn, left=left, right=right,
                         ins=ins_runs, dele=del_runs))
    return secs, to, tn


if __name__ == '__main__':
    secs, to, tn = build()
    for s in secs:
        print('s%-2d %4d -> %4d (%+4d)  绿%2d 红%2d  段 %d/%d' % (
            s['n'], s['ho'], s['hn'], s['hn'] - s['ho'], s['ins'], s['dele'],
            len(s['left']), len(s['right'])))
    print('合计', to, '->', tn)
