import json
from datetime import datetime

from django import template
from django.utils.html import format_html
from django.utils.safestring import mark_safe

from servala.core.crd.utils import deslugify

register = template.Library()


@register.filter
def pprint(value):
    if isinstance(value, (dict, list)):
        return json.dumps(value, indent=2)
    return value


@register.filter
def localtime_tag(value, format_str="datetime"):
    """
    Render a datetime value as a <time> element with datetime attribute.
    JavaScript will convert this to local time on page load.

    Usage: {{ instance.created_at|localtime_tag }}
           {{ instance.created_at|localtime_tag:"date" }}
           {{ instance.created_at|localtime_tag:"time" }}
    """
    if value is None:
        return "-"

    if isinstance(value, str):
        iso_value = value
    elif isinstance(value, datetime):
        iso_value = value.isoformat()
    else:
        return str(value)

    if (
        not iso_value.endswith("Z")
        and "+" not in iso_value
        and "-" not in iso_value[10:]
    ):
        iso_value += "Z"

    return format_html(
        '<time datetime="{}" data-format="{}" class="local-time">{}</time>',
        iso_value,
        format_str,
        iso_value,
    )


@register.filter
def render_tree(value, key=""):
    """
    Render a nested dict/list as a collapsible tree structure.
    Used for displaying JSON parameters in a user-friendly way.
    """
    if value is None:
        return mark_safe('<span class="text-muted">-</span>')

    if isinstance(value, bool):
        badge_class = "bg-success" if value else "bg-secondary"
        return format_html(
            '<span class="badge {}">{}</span>',
            badge_class,
            "Yes" if value else "No",
        )

    if isinstance(value, (str, int, float)):
        if isinstance(value, str) and len(value) > 100:
            return format_html("<code>{}</code>", value)
        return format_html("<span>{}</span>", value)

    if isinstance(value, list):
        if not value:
            return mark_safe('<span class="text-muted">[]</span>')
        # For simple string/number arrays, render as comma-separated or line-separated
        if all(isinstance(item, (str, int, float)) for item in value):
            if len(value) == 1:
                return format_html("<span>{}</span>", value[0])
            # Multiple items: render each on its own line
            items = [format_html("<div>{}</div>", item) for item in value]
            return mark_safe("".join(items))
        # For complex arrays (dicts, nested lists), use list structure
        items = []
        for item in value:
            items.append(f"<li>{render_tree(item)}</li>")
        return mark_safe(f'<ul class="list-unstyled mb-0">{"".join(items)}</ul>')

    if isinstance(value, dict):
        if not value:
            return mark_safe('<span class="text-muted">{}</span>')
        items = []
        for k, v in value.items():
            rendered_value = render_tree(v, k)
            items.append(
                f'<dt class="col-sm-4 text-truncate" title="{k}">{deslugify(k)}</dt>'
                f'<dd class="col-sm-8">{rendered_value}</dd>'
            )
        return mark_safe(f'<dl class="row mb-0">{"".join(items)}</dl>')

    return format_html("<span>{}</span>", str(value))
