#!/usr/bin/env python3
"""Generiert tokens.css aus tokens.json.

OKLCH als primäre CSS-Variablen, HEX-Fallback via @supports.
Aliase werden als var(--zielvariable) ausgegeben, sodass OKLCH-Browser
automatisch den OKLCH-Wert sehen und Fallback-Browser den HEX-Wert.

Aufruf:
    python _build_css.py

Output: Tokens/tokens.css (überschreibt).
"""
from __future__ import annotations

import json
import re
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
TOKENS_JSON = HERE / "tokens.json"
TOKENS_CSS = HERE / "tokens.css"

ALIAS_RE = re.compile(r"\{([^}]+)\}")
PURE_ALIAS_RE = re.compile(r"^\s*\{([^}]+)\}\s*$")

# Top-Level-Kategorien, aus denen CSS-Variablen erzeugt werden.
# Ausgelassen: $meta, typography (Font-Strings sind keine CSS-Var-Kandidaten
# in dieser Form), component (geschachtelt, kein direkter CSS-Var-Nutzen).
INCLUDE_TOPS = (
    "color", "spacing", "radius", "shadow", "motion",
    "breakpoint", "container", "grid", "icon",
    "focus-ring", "border-width", "z-index",
)


def get_by_path(root: dict, dotted: str):
    node = root
    for part in dotted.split("."):
        if not isinstance(node, dict) or part not in node:
            return None
        node = node[part]
    return node


def resolve_value(raw, root: dict, depth: int = 0) -> str:
    """Ersetzt {alias.pfad} im String durch den tatsächlichen Wert (rekursiv)."""
    if not isinstance(raw, str) or depth > 8:
        return str(raw)

    def repl(m: re.Match) -> str:
        target = get_by_path(root, m.group(1))
        if isinstance(target, dict) and "value" in target:
            return resolve_value(target["value"], root, depth + 1)
        return m.group(0)

    return ALIAS_RE.sub(repl, raw)


def is_pure_alias(value) -> bool:
    return isinstance(value, str) and bool(PURE_ALIAS_RE.match(value))


def alias_to_var(value: str) -> str:
    m = PURE_ALIAS_RE.match(value)
    assert m is not None
    return f"var(--{m.group(1).replace('.', '-')})"


def is_scalar_leaf(node) -> bool:
    if not isinstance(node, dict) or "value" not in node:
        return False
    v = node["value"]
    # text-style-Composite (font-family/font-size/...) überspringen.
    if isinstance(v, dict):
        return False
    return True


def walk(node: dict, prefix: list, out: list) -> None:
    for key, child in node.items():
        if key.startswith("$") or not isinstance(child, dict):
            continue
        new_prefix = prefix + [key]
        if is_scalar_leaf(child):
            out.append(("-".join(new_prefix), child))
        else:
            walk(child, new_prefix, out)


def main() -> int:
    if not TOKENS_JSON.exists():
        print(f"FEHLER: {TOKENS_JSON} nicht gefunden.", file=sys.stderr)
        return 1

    with TOKENS_JSON.open("r", encoding="utf-8") as f:
        tokens = json.load(f)

    meta = tokens.get("$meta", {})
    version = meta.get("version", "?")
    date = meta.get("date", "?")

    leaves = []
    for top_key in INCLUDE_TOPS:
        if top_key in tokens:
            walk({top_key: tokens[top_key]}, [], leaves)

    primary, fallback = [], []

    for path, leaf in leaves:
        var = f"--{path}"
        raw = leaf.get("value")
        oklch = leaf.get("$oklch")

        if is_pure_alias(raw):
            primary.append(f"  {var}: {alias_to_var(raw)};")
            continue

        if oklch:
            primary.append(f"  {var}: {oklch};")
            fallback.append(f"    {var}: {raw};")
            continue

        primary.append(f"  {var}: {resolve_value(raw, tokens)};")

    lines = [
        "/* Warm Navigator Design Tokens */",
        f"/* Generated by _build_css.py from tokens.json v{version} ({date}). */",
        "/* Do not edit by hand. Run: python _build_css.py */",
        "",
        ":root {",
        *primary,
        "}",
        "",
    ]

    if fallback:
        lines += [
            "@supports not (color: oklch(0% 0 0)) {",
            "  :root {",
            *fallback,
            "  }",
            "}",
            "",
        ]

    TOKENS_CSS.write_text("\n".join(lines), encoding="utf-8")
    print(f"OK: {TOKENS_CSS.name} geschrieben ({len(leaves)} Tokens, "
          f"{len(fallback)} OKLCH→HEX-Fallbacks).")
    return 0


if __name__ == "__main__":
    sys.exit(main())
