"""Scaffold a new demo page: www/<slug>/index.html (+ style.css), its entry in CATEGORIES
(scripts/gen_nav.py), its card on the home page, then regenerate every page's nav.

Run from the repo root:
    python3 scripts/new_demo.py <category> <slug> --name 短名 --icon 🧩 \\
        --title '页面标题' --subtitle '副标题（可含 HTML）' --help-html '操作提示' \\
        --card-desc '首页卡片一句话' --tag '卡片标签' [--body body.html] [--css]

The crate (crates/<category>/<slug>/), index.js and scripts/explain/<slug>.json are still
written by hand; after writing the explain JSON run `python3 scripts/gen_explain.py <slug>`.
"""
import argparse
import html
import importlib.util
import pathlib
import re
import subprocess
import sys

ROOT = pathlib.Path(__file__).resolve().parent.parent


def page_html(title, h1, subtitle, body, help_html, own_css):
    """The page skeleton every demo shares; nav and explain panel are filled in by generators."""
    css = '\n    <link rel="stylesheet" href="style.css">' if own_css else ''
    body = body.rstrip('\n') or '        <p id="perf-info" class="status-line"></p>'
    return f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
    <title>{html.escape(title)} — Rust + WebAssembly</title>
    <link rel="stylesheet" href="../style.css">
    <link rel="stylesheet" href="../explain.css">{css}
    <script src="../nav.js" defer></script>
</head>
<body class="has-nav">
    <nav class="top-nav"></nav>

    <div id="container">
        <h1>{html.escape(h1)}</h1>
        <p class="subtitle">{subtitle}</p>

{body}

        <p class="help">
            {help_html}
        </p>
        <details class="explain"></details>
    </div>

    <script type="module" src="index.js"></script>
</body>
</html>
'''


def add_to_categories(source, category, slug, name):
    """Return gen_nav.py source with (slug, name) appended to the category's demo list."""
    start = re.search(rf"^    \('{re.escape(category)}', ", source, re.M)
    if not start:
        raise ValueError(f'unknown category: {category}')
    end = source.index('    ]),\n', start.end())
    if f"('{slug}', " in source[start.start():end]:
        raise ValueError(f'{slug} is already in {category}')
    entry = f"        ('{slug}', '{name}'),\n"
    return source[:end] + entry + source[end:]


def add_card(home, category, label, description, slug, icon, title, desc, tag):
    """Return the home page with a card for the demo in its category's section
    (creating the section after the previous existing category if needed)."""
    if f'href="{slug}/"' in home:
        raise ValueError(f'{slug} already has a card')
    card = f'''            <a href="{slug}/" class="card">
                <div class="card-icon">{icon}</div>
                <h3>{html.escape(title)}</h3>
                <p>{html.escape(desc)}</p>
                <span class="card-tag">{html.escape(tag)}</span>
            </a>'''
    m = re.search(rf'(        <section class="cat" id="cat-{category}".*?<div class="card-grid">\n)(.*?)(\n            </div>\n        </section>)', home, re.S)
    if m:
        return home[:m.end(2)] + '\n\n' + card + home[m.end(2):]
    section = f'''        <section class="cat" id="cat-{category}" aria-labelledby="cat-{category}-title">
            <h2 class="cat-title" id="cat-{category}-title">{label}<small>{description}</small></h2>
            <div class="card-grid">
{card}
            </div>
        </section>'''
    last = list(re.finditer(r'^        </section>\n', home, re.M))
    if not last:
        raise ValueError('home page has no category sections')
    return home[:last[-1].end()] + '\n' + section + '\n' + home[last[-1].end():]


def load_categories():
    spec = importlib.util.spec_from_file_location('gen_nav', ROOT / 'scripts' / 'gen_nav.py')
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod.CATEGORIES


def main():
    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    ap.add_argument('category')
    ap.add_argument('slug')
    ap.add_argument('--name', required=True, help='short name for the top nav')
    ap.add_argument('--icon', required=True)
    ap.add_argument('--title', required=True, help='page title, also the home card title')
    ap.add_argument('--h1', help='page heading (default: --title)')
    ap.add_argument('--subtitle', required=True, help='HTML allowed')
    ap.add_argument('--help-html', required=True, help='HTML allowed')
    ap.add_argument('--card-desc', required=True)
    ap.add_argument('--tag', required=True)
    ap.add_argument('--body', help='file with the page body HTML (8-space indented)')
    ap.add_argument('--css', action='store_true', help='also create www/<slug>/style.css')
    a = ap.parse_args()

    if not re.fullmatch(r'[a-z0-9]+(-[a-z0-9]+)*', a.slug):
        sys.exit('slug must be lowercase words joined by "-"')
    categories = {key: (label, desc) for key, label, desc, _ in load_categories()}
    if a.category not in categories:
        sys.exit(f"unknown category {a.category!r}; one of: {', '.join(categories)}")
    page_dir = ROOT / 'www' / a.slug
    if (page_dir / 'index.html').exists():
        sys.exit(f'{page_dir}/index.html already exists')

    # Validate every edit before writing anything
    nav_path, home_path = ROOT / 'scripts' / 'gen_nav.py', ROOT / 'www' / 'index.html'
    try:
        nav_src = add_to_categories(nav_path.read_text(encoding='utf-8'), a.category, a.slug, a.name)
        label, desc = categories[a.category]
        home = add_card(home_path.read_text(encoding='utf-8'), a.category, label, desc,
                        a.slug, a.icon, a.title, a.card_desc, a.tag)
    except ValueError as e:
        sys.exit(str(e))
    body = pathlib.Path(a.body).read_text(encoding='utf-8') if a.body else ''

    page_dir.mkdir(parents=True)
    (page_dir / 'index.html').write_text(page_html(a.title, a.h1 or a.title, a.subtitle, body, a.help_html, a.css), encoding='utf-8')
    if a.css:
        (page_dir / 'style.css').write_text(f'/* {a.slug} demo */\n', encoding='utf-8')
    nav_path.write_text(nav_src, encoding='utf-8')
    home_path.write_text(home, encoding='utf-8')
    subprocess.run([sys.executable, str(nav_path)], check=True, stdout=subprocess.DEVNULL)
    print(f'created www/{a.slug}/ · added to {a.category} · home card · nav regenerated')
    print(f'next: crates/{a.category}/{a.slug}/, www/{a.slug}/index.js, scripts/explain/{a.slug}.json')


if __name__ == '__main__':
    main()
