"""Custom Jinja2 helpers and filters for dotprompt templates.

Provides built-in globals (role, media) and filters (tojson).
Note: ifEquals/unlessEquals are removed; use native Jinja2 conditionals instead.
"""

import json
from collections.abc import Callable
from typing import Any


def tojson_filter(obj: Any, indent: int = 0) -> str:  # noqa: ANN401
    """Jinja2 filter: convert a value to a JSON string.

    Args:
        obj: The value to convert to JSON.
        indent: JSON indentation (0 means compact).

    Returns:
        JSON string representation of the value.

    Raises:
        TypeError: If the value cannot be serialized to JSON.
        ValueError: If the value contains invalid data for JSON serialization.
    """
    if isinstance(indent, str):
        try:
            indent = int(indent)
        except (ValueError, TypeError):
            indent = 0

    if indent == 0:
        return json.dumps(obj, separators=(',', ':'), ensure_ascii=False)
    return json.dumps(obj, indent=indent, ensure_ascii=False)


def role(name: str) -> str:
    """Create a dotprompt role marker.

    Example (Jinja2)::

        {{role('system')}}

    Args:
        name: The role name (e.g. ``"system"``, ``"user"``, ``"model"``).

    Returns:
        Role marker of the form ``<<<dotprompt:role:...>>>``.
    """
    return f'<<<dotprompt:role:{name}>>>'


def media(url: str = '', content_type: str = '', **kwargs: str) -> str:
    """Create a dotprompt media marker.

    Example (Jinja2)::

        {{media(url=imageUrl, contentType='image/png')}}

    Args:
        url: The media resource URL or base64 data.
        content_type: MIME type (e.g. ``"image/png"``).
        **kwargs: Backward-compatible aliases (supports ``contentType``).

    Returns:
        Media marker of the form ``<<<dotprompt:media:url ...>>>``.
    """
    if not url:
        return ''

    legacy_content_type = kwargs.pop('contentType', '')
    if kwargs:
        unknown = ', '.join(sorted(kwargs))
        raise TypeError(f'Unexpected keyword argument(s): {unknown}')

    resolved_content_type = content_type or legacy_content_type
    if resolved_content_type:
        return f'<<<dotprompt:media:url {url} {resolved_content_type}>>>'
    return f'<<<dotprompt:media:url {url}>>>'


BUILTIN_HELPERS: dict[str, Callable[..., str]] = {
    'media': media,
    'role': role,
}
"""Mapping of built-in helper names to their callable implementations.

These are registered as ``jinja2.Environment.globals`` so they can be
called directly in templates: ``{{ role("system") }}``.
"""

BUILTIN_FILTERS: dict[str, Callable[..., str]] = {
    'tojson': tojson_filter,
}
"""Mapping of built-in filter names to their callable implementations.

These are registered as ``jinja2.Environment.filters`` so they can be
used in templates: ``{{ data | tojson(indent=2) }}``.
"""
