import json

from django.conf import settings
from django.contrib import messages as django_messages
from django.contrib.messages import constants as message_constants

MESSAGE_LEVEL_MAP = {
    message_constants.DEBUG: "debug",
    message_constants.INFO: "info",
    message_constants.SUCCESS: "success",
    message_constants.WARNING: "warning",
    message_constants.ERROR: "error",
}


class HTMXMessagesMiddleware:
    """
    Converts Django messages into HX-Trigger headers so toasts display
    automatically without changes to views.

    Works for HTMX requests (processed natively by HTMX client),
    vanilla fetch() calls using fetchWithHtmxTriggers(), and is harmless
    for full-page loads (browsers ignore HX-Trigger).
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)

        # Skip HX-Trigger and don't consume messages if there's an HX-Redirect
        # so the message persists in the session for the redirect target page
        if "HX-Redirect" in response:
            return response

        min_level = (
            message_constants.DEBUG if settings.DEBUG else message_constants.INFO
        )
        backend = django_messages.get_messages(request)
        if hasattr(backend, "_set_level") and backend._get_level() > min_level:
            backend._set_level(min_level)
        messages = list(backend)
        if not messages:
            return response

        triggers = []
        for msg in messages:
            toast_type = MESSAGE_LEVEL_MAP.get(msg.level, "info")
            triggers.append(
                {
                    "message": msg.message,
                    "type": toast_type,
                }
            )

        if triggers:
            # Use last message (most recent) as the primary toast
            trigger = triggers[-1]
            response["HX-Trigger"] = json.dumps(
                {
                    "show-toast": trigger,
                }
            )

        return response
