#!/usr/bin/env python3
"""The kit's demo app — serve the living styleguide (M1 P4.1).

A dev-only, stdlib-http server that renders the SHIPPED template pack
(``mgf/styleguide.html`` extending ``mgf/console.html``, macros included) with
the SHIPPED static assets — the kit demonstrating itself end-to-end, replacing
the old hand-copied, unserved ``docs/instruments-demo.html`` gallery.

Run from the repo (jinja2 comes with the ``[dev]`` extra)::

    .venv/bin/python demo/app.py            # http://127.0.0.1:8791/

This lives OUTSIDE the package on purpose: ``mgf.brand_web`` ships assets only
and imports no web framework (import-linter contract) — jinja2 is a dev-time
tool here, never a runtime dependency of the kit.
"""

from __future__ import annotations

import contextlib
import re
import sys
from functools import partial
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))

import jinja2  # noqa: E402  (dev extra; deliberately after the src path insert)

from mgf.brand_web import __version__, static_dir, templates_dir  # noqa: E402

HOST, PORT = "127.0.0.1", 8791


def icon_names() -> list[str]:
    """Every symbol id in the vendored sprite, in sheet order, un-prefixed."""
    sprite = (static_dir() / "icons" / "icons-sprite.svg").read_text(encoding="utf-8")
    return [m.group(1) for m in re.finditer(r'<symbol id="mgf-icon-([a-z0-9-]+)"', sprite)]


def render_styleguide() -> bytes:
    env = jinja2.Environment(
        loader=jinja2.FileSystemLoader(str(templates_dir())),
        autoescape=True,
    )
    page = env.get_template("mgf/styleguide.html").render(
        icon_names=icon_names(), kit_version=__version__
    )
    return page.encode("utf-8")


class Handler(SimpleHTTPRequestHandler):
    """`/` → the rendered styleguide; `/static/brand/*` → the kit static dir."""

    def do_GET(self) -> None:  # the http.server API name
        if self.path in ("/", "/index.html"):
            body = render_styleguide()  # re-rendered per request: live editing
            self.send_response(200)
            self.send_header("Content-Type", "text/html; charset=utf-8")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        if self.path == "/static/app.css":  # the shell links it; the demo has none
            self.send_response(200)
            self.send_header("Content-Type", "text/css")
            self.send_header("Content-Length", "0")
            self.end_headers()
            return
        if self.path.startswith("/static/brand/"):
            # Strip the mount prefix; the base handler serves from static_dir().
            self.path = self.path.removeprefix("/static/brand")
            super().do_GET()
            return
        self.send_error(404)


def main() -> None:
    handler = partial(Handler, directory=str(static_dir()))
    with ThreadingHTTPServer((HOST, PORT), handler) as httpd:
        print(f"mgf-brand-web {__version__} styleguide → http://{HOST}:{PORT}/")
        with contextlib.suppress(KeyboardInterrupt):
            httpd.serve_forever()


if __name__ == "__main__":
    main()
