"""
Handlebars-light Template-Renderer fuer die compliance_legal_templates.

Unterstuetzte Syntax:
- {{VARIABLE_NAME}}          - einfache String-Substitution
- {{#IF FLAG}}...{{/IF}}      - bedingter Block (truthy)
- {{#IF NOT FLAG}}...{{/IF}}  - negierter bedingter Block

Bewusst minimal gehalten — keine Loops oder Verschachtelung tiefer Logik.
Komplexere Sachen werden im Context vorberechnet.
"""

from __future__ import annotations

import re
from typing import Any

# Innerste {{#IF FLAG}}...{{/IF}}-Bloecke (Content enthaelt KEIN weiteres {{#IF).
# Iteratives Anwenden loest Verschachtelung von innen nach aussen sauber auf.
IF_INNERMOST = re.compile(
    r"\{\{#IF\s+(NOT\s+)?([A-Z_][A-Z0-9_]*)\}\}"
    r"((?:(?!\{\{#IF).)*?)"  # Content: kein weiteres {{#IF
    r"\{\{/IF\}\}",
    re.DOTALL,
)
VAR_PATTERN = re.compile(r"\{\{\s*([A-Z_][A-Z0-9_]*)\s*\}\}")
# Fallback: orphan IF-Tags die nach Iteration uebrig sind (z.B. unbalanced template) raus.
ORPHAN_IF_TAG = re.compile(
    r"\{\{/IF\}\}|\{\{#IF\s+(?:NOT\s+)?[A-Z_][A-Z0-9_]*\}\}"
)


def _is_truthy(val: Any) -> bool:
    """Pythonische Truthiness, mit Special-Case: leeres dict/list/str = False."""
    if val is None:
        return False
    if isinstance(val, bool):
        return val
    if isinstance(val, (int, float)):
        return val != 0
    if isinstance(val, str):
        return val.strip() != "" and val.lower() not in ("false", "0", "no", "nein")
    if isinstance(val, (list, dict, tuple, set)):
        return len(val) > 0
    return True


def render_template(template: str, context: dict[str, Any]) -> str:
    """Rendert ein Template mit dem gegebenen Kontext.

    Algorithmus:
    1. IF-Bloecke iterativ aufloesen (max 10 Durchlaeufe, damit Nesting funktioniert)
    2. Variablen substituieren

    Args:
        template: Markdown-Template mit {{VAR}} und {{#IF FLAG}}...{{/IF}}
        context: dict mit Variablen — Keys SCREAMING_SNAKE_CASE

    Returns:
        Gerendetes Markdown
    """
    output = template

    # IF-Bloecke iterativ aufloesen — innerste zuerst, dann eine Ebene hoeher, usw.
    # Bis zu 20 Iterationen reichen fuer realistisches Nesting.
    for _ in range(20):
        def replace_if(match: re.Match[str]) -> str:
            negated = bool(match.group(1))
            flag_name = match.group(2)
            content = match.group(3)
            flag_val = context.get(flag_name)
            condition = _is_truthy(flag_val)
            if negated:
                condition = not condition
            return content if condition else ""

        new_output = IF_INNERMOST.sub(replace_if, output)
        if new_output == output:
            break
        output = new_output

    # Falls noch orphan IF-Tags uebrig sind (z.B. unbalanced template): entfernen
    # damit sie nicht im Word-Output landen.
    output = ORPHAN_IF_TAG.sub("", output)

    def replace_var(match: re.Match[str]) -> str:
        name = match.group(1)
        val = context.get(name)
        if val is None:
            # Leere Platzhalter sichtbar machen fuer Debugging
            return f"[{name} fehlt]"
        if isinstance(val, bool):
            return "ja" if val else "nein"
        return str(val)

    output = VAR_PATTERN.sub(replace_var, output)
    return output


def find_undefined_placeholders(template: str, context: dict[str, Any]) -> list[str]:
    """Listet alle Variablen-Platzhalter ohne Wert im Context."""
    placeholders: set[str] = set()
    for match in VAR_PATTERN.finditer(template):
        placeholders.add(match.group(1))
    for match in IF_INNERMOST.finditer(template):
        placeholders.add(match.group(2))
    return sorted([p for p in placeholders if p not in context])
