#!/usr/bin/env python3
"""Render one of the design documents to PDF.

    python3 worker/make_pdf.py in.html out.pdf ["Footer text"]

WeasyPrint resolves neither CSS custom properties nor an internal <style> block
inside an <svg>, so a diagram styled by class comes out as solid black boxes.
Both are handled here for the print copy only: var(--token) is substituted from
the document's own :root block, and SVG classes are baked down into
presentation attributes. The web version keeps its tokens.
"""
from __future__ import annotations

import re
import sys
from pathlib import Path

BASE = Path(__file__).resolve().parent.parent
_vendor = BASE / "vendor"
if _vendor.is_dir():
    sys.path.insert(0, str(_vendor))

# class -> presentation attributes, for diagrams drawn with the shared palette
SVG_ATTRS = {
    "bx":  'fill="#11141f" stroke="#6b7089" stroke-width="1.1"',
    "bx1": 'fill="#231f52" stroke="#8b7ff5" stroke-width="1.4"',
    "bx3": 'fill="#0d2f2c" stroke="#22a99d" stroke-width="1.4"',
    "tt":  'font-family="Helvetica,Arial,sans-serif" font-size="12.5" font-weight="700" fill="#eef0f8"',
    "ss":  'font-family="monospace" font-size="9" fill="#9ea4bd"',
    "ee":  'font-family="monospace" font-size="8.5" fill="#8b7ff5"',
    "ln":  'stroke="#c8cde0" stroke-width="1.2" fill="none"',
    "lnc": 'stroke="#8b7ff5" stroke-width="1.3" fill="none" stroke-dasharray="5 4"',
}

PRINT_CSS = """
<style>
  @page { size: A4; margin: 14mm 12mm 16mm 12mm;
          @bottom-center { content: "%(footer)s - page " counter(page) " of " counter(pages);
                           font-family: monospace; font-size: 7.5pt; color: #6b7089; } }
  html, body { background: #080a12 !important }
  body { font-size: 10.2pt }
  .wrap { max-width: none; padding: 0 }
  header { padding-top: 0 }
  h1 { font-size: 28pt }
  h2 { break-after: avoid; margin-top: 22px }
  figure, .math, .card, .note { break-inside: avoid }
  tr { break-inside: avoid }
  table { min-width: 0 }
  .scroll { overflow: visible }
  .cols { display: block } .card { margin-bottom: 12px }
  td, th { padding-right: 10px }
</style>"""


def convert(src: Path, out: Path, footer: str = "GSIQ Crystal") -> Path:
    html = src.read_text()
    title_m = re.search(r"<title>(.*?)</title>", html)
    title = title_m.group(1) if title_m else src.stem
    body = html.split("</title>", 1)[1] if title_m else html
    marker = '<div class="wrap">'
    head_part, rest = body.split(marker, 1)

    tokens = dict(re.findall(r"--([a-z0-9-]+)\s*:\s*([^;]+);", head_part))

    def literal(s: str) -> str:
        for k, v in tokens.items():
            s = s.replace(f"var(--{k})", v.strip())
        return s

    for svg in re.findall(r"<svg[\s\S]*?</svg>", rest):
        baked = re.sub(r"<style>[\s\S]*?</style>", "", svg, count=1)
        baked = re.sub(r'class="(%s)"' % "|".join(sorted(SVG_ATTRS, key=len, reverse=True)),
                       lambda m: SVG_ATTRS[m.group(1)], baked)
        baked = (baked.replace('fill="currentColor"', 'fill="#c8cde0"')
                      .replace('stroke="currentColor"', 'stroke="#c8cde0"'))
        rest = rest.replace(svg, literal(baked))

    doc = ('<!doctype html><html lang="en"><head><meta charset="utf-8">'
           f'<title>{title}</title>{literal(head_part)}'
           f'{PRINT_CSS % {"footer": footer}}</head><body>{marker}{literal(rest)}</body></html>')

    from weasyprint import HTML
    HTML(string=doc, base_url=str(src.parent)).write_pdf(str(out))
    return out


if __name__ == "__main__":
    if len(sys.argv) < 3:
        print(__doc__)
        raise SystemExit(2)
    footer = sys.argv[3] if len(sys.argv) > 3 else "GSIQ Crystal"
    p = convert(Path(sys.argv[1]), Path(sys.argv[2]), footer)
    print(f"wrote {p} ({p.stat().st_size:,} bytes)")
