"""Render the 原理说明 panel of each demo page from scripts/explain/<demo>.json.

Run from the repo root:  python3 scripts/gen_explain.py [demo ...]

Each www/<demo>/index.html must contain exactly one explain block
(for a new page, a placeholder `<details class="explain"></details>` is enough).
The home page panel (www/index.html) is hand-written and not managed here.
Panels start collapsed (no `open`); the header shows 展开 / 收起.

JSON fields (all strings are HTML fragments):
  lead         str                     intro paragraph
  formulas     [[expr, note], ...]     key formulas; note may be ""
  terms        [[term, desc], ...]     算法原理 definition list
  terms_notes  [str]                   notes after the list
  flow         [[actor, text], ...]    actor: js | rust | gpu
  flow_notes   [str]
  perf         [str]                   性能要点 bullets
  src          [[path, note], ...]     note may be ""
"""
import json
import pathlib
import re
import sys

ROOT = pathlib.Path(__file__).resolve().parent.parent
DATA = ROOT / 'scripts' / 'explain'
ACTOR = {'js': 'JS', 'rust': 'Rust', 'gpu': 'GPU'}
BLOCK_RE = re.compile(r'        <details class="explain"[^>]*>.*?</details>\n', re.S)
I = '            '


def render(d):
    out = ['        <details class="explain">',  # collapsed until the reader opens it
           f'{I}<summary><span class="explain-title">📖 原理说明</span>'
           '<span class="explain-toggle" aria-hidden="true"></span></summary>',
           f'{I}<p class="explain-lead">{d["lead"]}</p>',
           f'{I}<section class="explain-sec">',
           f'{I}    <h3><span class="explain-ico">🧮</span>算法原理</h3>']
    for expr, note in d.get('formulas', []):
        note_html = f'<span class="explain-formula-note">{note}</span>' if note else ''
        out.append(f'{I}    <div class="explain-formula">'
                   f'<span class="explain-formula-expr">{expr}</span>{note_html}</div>')
    if d.get('terms'):
        out.append(f'{I}    <dl class="explain-terms">')
        for term, desc in d['terms']:
            out.append(f'{I}        <dt>{term}</dt>')
            out.append(f'{I}        <dd>{desc}</dd>')
        out.append(f'{I}    </dl>')
    for p in d.get('terms_notes', []):
        out.append(f'{I}    <p class="explain-note">{p}</p>')
    out.append(f'{I}</section>')

    out += [f'{I}<section class="explain-sec">',
            f'{I}    <h3><span class="explain-ico">🔄</span>Rust 与 JavaScript 的分工</h3>',
            f'{I}    <ol class="explain-flow">']
    for actor, text in d['flow']:
        out.append(f'{I}        <li><span class="explain-actor {actor}">{ACTOR[actor]}</span>'
                   f'<span>{text}</span></li>')
    out.append(f'{I}    </ol>')
    for p in d.get('flow_notes', []):
        out.append(f'{I}    <p class="explain-note">{p}</p>')
    out.append(f'{I}</section>')

    out += [f'{I}<section class="explain-sec explain-perf">',
            f'{I}    <h3><span class="explain-ico">⚡</span>性能要点</h3>',
            f'{I}    <ul>']
    out += [f'{I}        <li>{p}</li>' for p in d['perf']]
    out += [f'{I}    </ul>', f'{I}</section>']

    chips = ''
    for path, note in d['src']:
        chips += f'<code class="explain-chip">{path}</code>'
        if note:
            chips += f'<span class="explain-src-note">{note}</span>'
    out.append(f'{I}<p class="explain-src"><span>源码</span>{chips}</p>')
    out.append('        </details>')
    return '\n'.join(out) + '\n'


def main(names):
    names = names or sorted(p.stem for p in DATA.glob('*.json'))
    for name in names:
        data = json.loads((DATA / f'{name}.json').read_text(encoding='utf-8'))
        page = ROOT / 'www' / name / 'index.html'
        html = page.read_text(encoding='utf-8')
        found = len(BLOCK_RE.findall(html))
        if found != 1:
            sys.exit(f'{page}: expected 1 explain block, found {found}')
        page.write_text(BLOCK_RE.sub(lambda _: render(data), html), encoding='utf-8')
        print(f'rendered {name}')


if __name__ == '__main__':
    main(sys.argv[1:])
