"""preview_all.py — Browser-Vorschau-Generator für alle Templates einer Aspect-Ratio.

Baut eine einzelne HTML-Seite mit allen Template-Vorschauen für ein gegebenes
Basisbild + Headline + Eyebrow + Logo-Wahl. Jede Vorschau zeigt das echte Foto
in der echten Größe (skaliert für die Übersicht), so dass der Anwender im
Browser sofort sieht, welches Layout zum konkreten Bild passt.

Aspect-Ratios:
    --aspect 16x9 (Default): rendert die 27 Bestand-Templates aus compose.py
    --aspect 4x5             : rendert die 4:5-Hochformat-Templates aus compose_v.py
                               (LinkedIn-Default für Single-Image-Posts)

Optional --recommend T01: hebt eine Karte als Empfehlung hervor.
Optional --open: öffnet die HTML-Seite nach dem Schreiben im Standard-Browser.

CLI:
    python -m _lib.designsystem.preview_all \
        --photo <PFAD> \
        [--aspect 16x9|4x5] \
        --headline "..." [--eyebrow "..."] [--logo] [--logo-path PATH] \
        [--recommend T01] [--open] \
        --output <preview.html>
"""

from __future__ import annotations

import argparse
import os
import subprocess
import sys
import webbrowser
from html import escape
from pathlib import Path

from _lib.designsystem import compose, compose_v
from _lib.designsystem.compose import (
    C_DEEP_SEA, C_CREAM, C_GOLD, C_TEAL,
    FONT_BODY, FONT_HEAD, set_logo_path,
)
from _lib.designsystem.resolve import resolve_designsystem


def load_template_module(aspect: str):
    """Liefert das Template-Modul je Aspect-Ratio."""
    if aspect == "16x9":
        return compose
    if aspect == "4x5":
        return compose_v
    raise SystemExit(f"Unbekannte Aspect-Ratio '{aspect}'. Erlaubt: 16x9, 4x5")


PAGE = """<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Thumbnail-Vorschau · {title_count} Templates · {aspect_label}</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Mona+Sans:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap">
<style>
  :root {{
    --deep-sea: {deep};
    --cream: {cream};
    --gold: {gold};
    --teal: {teal};
  }}
  * {{ box-sizing: border-box; }}
  html, body {{
    margin: 0; padding: 0;
    background: var(--deep-sea);
    color: var(--cream);
    font-family: {fbody};
  }}
  header {{
    padding: 28px 48px 18px;
    border-bottom: 1px solid rgba(248,246,242,0.08);
    background: linear-gradient(180deg, rgba(248,246,242,0.04), transparent);
    position: sticky; top: 0; z-index: 10;
    backdrop-filter: blur(12px);
  }}
  h1 {{
    margin: 0 0 6px;
    font-family: {fhead};
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.5px;
  }}
  .meta {{
    font-size: 13px;
    color: rgba(248,246,242,0.65);
    line-height: 1.5;
  }}
  .meta b {{ color: var(--cream); font-weight: 600; }}
  .grid {{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax({grid_min}px, 1fr));
    gap: 28px;
    padding: 28px 48px 48px;
  }}
  .card {{
    background: rgba(248,246,242,0.04);
    border: 1px solid rgba(248,246,242,0.08);
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: transform .15s ease, border-color .15s ease;
  }}
  .card:hover {{ transform: translateY(-2px); border-color: rgba(248,246,242,0.18); }}
  .card.recommend {{
    border-color: var(--gold);
    box-shadow: 0 0 0 1px var(--gold);
  }}
  .card .label {{
    padding: 14px 18px 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font-family: {fhead};
    border-bottom: 1px solid rgba(248,246,242,0.06);
  }}
  .card .label .id {{
    font-weight: 700;
    font-size: 16px;
    letter-spacing: -0.3px;
  }}
  .card .label .name {{
    font-size: 13px;
    color: rgba(248,246,242,0.7);
    font-weight: 500;
    flex: 1;
    text-align: left;
    margin-left: 10px;
  }}
  .card .label .badge {{
    font-family: {fbody};
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    padding: 4px 8px;
    border-radius: 999px;
  }}
  .badge.with-logo {{ background: rgba(13,148,136,0.18); color: var(--teal); }}
  .badge.no-logo {{ background: rgba(248,246,242,0.06); color: rgba(248,246,242,0.55); }}
  .badge.empfehlung {{ background: var(--gold); color: var(--deep-sea); }}
  .frame {{
    position: relative;
    width: 100%;
    aspect-ratio: {ar};
    background: var(--deep-sea);
    overflow: hidden;
  }}
  .stage {{
    position: absolute;
    top: 0; left: 0;
    width: {w}px;
    height: {h}px;
    transform-origin: top left;
  }}
</style>
<script>
  function fitStages() {{
    document.querySelectorAll('.frame').forEach(frame => {{
      const stage = frame.querySelector('.stage');
      if (!stage) return;
      const scale = frame.clientWidth / {w};
      stage.style.transform = `scale(${{scale}})`;
    }});
  }}
  window.addEventListener('load', fitStages);
  window.addEventListener('resize', fitStages);
</script>
</head>
<body>
<header>
  <h1>Thumbnail-Vorschau · {title_count} Templates · {aspect_label}</h1>
  <div class="meta">
    Headline: <b>„{headline}"</b> · Eyebrow: <b>{eyebrow}</b> · Logo: <b>{logo_state}</b>
    {recommend_meta}
  </div>
</header>
<div class="grid">
{cards}
</div>
</body>
</html>
"""


CARD = """<div class="card{rec_cls}">
  <div class="label">
    <span class="id">{id_}</span>
    <span class="name">{name}</span>
    {badges}
  </div>
  <div class="frame">
    <div class="stage">{body}</div>
  </div>
</div>"""


def build_preview(photo_url: str, headline: str, eyebrow: str, logo: bool,
                  recommend: str | None, mod) -> str:
    photo_uri = photo_url
    templates = mod.TEMPLATES
    template_names = mod.TEMPLATE_NAMES
    template_logo_default = mod.TEMPLATE_LOGO_DEFAULT
    width, height = mod.WIDTH, mod.HEIGHT

    cards = []
    for tid in sorted(templates):
        body = templates[tid](photo_uri, headline, eyebrow, logo)
        is_rec = recommend == tid
        logo_default = template_logo_default.get(tid, False)
        badges = []
        if is_rec:
            badges.append('<span class="badge empfehlung">Empfehlung</span>')
        badges.append(
            '<span class="badge with-logo">mit Logo</span>'
            if logo_default
            else '<span class="badge no-logo">ohne Logo</span>'
        )
        cards.append(
            CARD.format(
                rec_cls=" recommend" if is_rec else "",
                id_=escape(tid),
                name=escape(template_names[tid]),
                badges="".join(badges),
                body=body,
            )
        )

    rec_meta = ""
    if recommend:
        rec_meta = (
            f' · Empfehlung: <b style="color:var(--gold)">{escape(recommend)}'
            f' — {escape(template_names.get(recommend, ""))}</b>'
        )

    aspect_label = f"{width}x{height} ({width}:{height})"
    if width / height > 1.5:
        aspect_label = f"16:9 quer · {width}x{height}"
        grid_min = 560
    elif abs(width / height - 1.0) < 0.05:
        aspect_label = f"1:1 quadratisch · {width}x{height}"
        grid_min = 460
    else:
        aspect_label = f"4:5 hochkant · {width}x{height}"
        grid_min = 380

    return PAGE.format(
        deep=C_DEEP_SEA,
        cream=C_CREAM,
        gold=C_GOLD,
        teal=C_TEAL,
        fbody=FONT_BODY,
        fhead=FONT_HEAD,
        w=width,
        h=height,
        ar=f"{width} / {height}",
        grid_min=grid_min,
        title_count=len(templates),
        aspect_label=aspect_label,
        headline=escape(headline),
        eyebrow=escape(eyebrow or "—"),
        logo_state="ja" if logo else "nein",
        recommend_meta=rec_meta,
        cards="\n".join(cards),
    )


def open_in_browser(path: Path) -> None:
    """Öffnet die Datei im Standard-Browser. Windows-freundlich."""
    uri = path.resolve().as_uri()
    if sys.platform == "win32":
        try:
            os.startfile(str(path.resolve()))  # type: ignore[attr-defined]
            return
        except OSError:
            pass
    elif sys.platform == "darwin":
        subprocess.run(["open", str(path)], check=False)
        return
    webbrowser.open(uri)


def _resolve_logo_path(logo_flag: bool, logo_path: Path | None) -> Path | None:
    if logo_path is not None:
        return logo_path
    if logo_flag:
        designsystem_root = resolve_designsystem()
        return designsystem_root / "assets" / "logo-placeholder.svg"
    return None


def main(argv: list[str] | None = None) -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("--photo", required=True, type=Path)
    ap.add_argument("--aspect", choices=["16x9", "4x5"], default="16x9",
                    help="Aspect-Ratio: 16x9 (Bestand, 27 Templates) oder 4x5 (LinkedIn-Default)")
    ap.add_argument("--headline", required=True)
    ap.add_argument("--eyebrow", default="")
    ap.add_argument("--logo", action="store_true",
                    help="Wenn gesetzt, alle Templates mit Logo rendern")
    ap.add_argument("--logo-path", type=Path, default=None,
                    help="Pfad zur Logo-SVG-Datei (überschreibt Bundle-Placeholder).")
    ap.add_argument("--recommend", default=None,
                    help="Template-ID, die als Empfehlung markiert wird (z.B. T01 oder T01v)")
    ap.add_argument("--open", action="store_true",
                    help="Vorschau-Seite nach dem Schreiben im Browser öffnen")
    ap.add_argument("--output", required=True, type=Path)
    args = ap.parse_args(argv)

    if not args.photo.is_file():
        print(f"FEHLER: Foto-Pfad nicht gefunden: {args.photo}", file=sys.stderr)
        return 2

    mod = load_template_module(args.aspect)
    args.output.parent.mkdir(parents=True, exist_ok=True)

    # Logo-Pfad setzen (deterministisch, Pflicht-Satz 6)
    set_logo_path(_resolve_logo_path(args.logo, args.logo_path))

    # Bild einmal neben die HTML-Datei kopieren statt N× als data-URI einzubetten
    photo_sibling = args.output.with_suffix(args.output.suffix + ".photo" + args.photo.suffix)
    photo_sibling.write_bytes(args.photo.read_bytes())
    photo_url = photo_sibling.name

    html = build_preview(photo_url, args.headline, args.eyebrow, args.logo, args.recommend, mod)
    args.output.write_text(html, encoding="utf-8")
    print(f"OK: {args.output}")

    if args.open:
        open_in_browser(args.output)

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
