"""
Tests for HTMX utility functions.

These tests verify that the HTMX response helpers generate
correct responses with proper headers and content.
"""

import json

import pytest
from django.test import RequestFactory

from apps.core.htmx_utils import (
    get_htmx_target,
    get_htmx_trigger,
    htmx_error,
    htmx_modal_close,
    htmx_redirect,
    htmx_refresh,
    htmx_refresh_section,
    htmx_success,
    htmx_trigger,
    htmx_validation_response,
    htmx_warning,
    is_htmx_request,
)


class TestIsHtmxRequest:
    """Tests for is_htmx_request function."""

    def test_returns_true_for_htmx_request(self):
        """Should return True when HX-Request header is 'true'."""
        factory = RequestFactory()
        request = factory.get("/", HTTP_HX_REQUEST="true")
        assert is_htmx_request(request) is True

    def test_returns_false_for_regular_request(self):
        """Should return False for regular requests without HTMX header."""
        factory = RequestFactory()
        request = factory.get("/")
        assert is_htmx_request(request) is False

    def test_returns_false_for_wrong_value(self):
        """Should return False when HX-Request header has wrong value."""
        factory = RequestFactory()
        request = factory.get("/", HTTP_HX_REQUEST="false")
        assert is_htmx_request(request) is False


class TestGetHtmxTarget:
    """Tests for get_htmx_target function."""

    def test_returns_target_when_present(self):
        """Should return target ID when HX-Target header is present."""
        factory = RequestFactory()
        request = factory.get("/", HTTP_HX_TARGET="my-target")
        assert get_htmx_target(request) == "my-target"

    def test_returns_none_when_missing(self):
        """Should return None when HX-Target header is missing."""
        factory = RequestFactory()
        request = factory.get("/")
        assert get_htmx_target(request) is None


class TestGetHtmxTrigger:
    """Tests for get_htmx_trigger function."""

    def test_returns_trigger_when_present(self):
        """Should return trigger ID when HX-Trigger header is present."""
        factory = RequestFactory()
        request = factory.get("/", HTTP_HX_TRIGGER="my-button")
        assert get_htmx_trigger(request) == "my-button"

    def test_returns_none_when_missing(self):
        """Should return None when HX-Trigger header is missing."""
        factory = RequestFactory()
        request = factory.get("/")
        assert get_htmx_trigger(request) is None


class TestHtmxRedirect:
    """Tests for htmx_redirect function."""

    def test_sets_redirect_header(self):
        """Should set HX-Redirect header with correct URL."""
        response = htmx_redirect("/parks/")
        assert response["HX-Redirect"] == "/parks/"

    def test_returns_empty_body(self):
        """Should return empty response body."""
        response = htmx_redirect("/parks/")
        assert response.content == b""


class TestHtmxTrigger:
    """Tests for htmx_trigger function."""

    def test_simple_trigger(self):
        """Should set simple trigger name."""
        response = htmx_trigger("myEvent")
        assert response["HX-Trigger"] == "myEvent"

    def test_trigger_with_payload(self):
        """Should set trigger with JSON payload."""
        response = htmx_trigger("myEvent", {"key": "value"})
        trigger_data = json.loads(response["HX-Trigger"])
        assert trigger_data == {"myEvent": {"key": "value"}}


class TestHtmxRefresh:
    """Tests for htmx_refresh function."""

    def test_sets_refresh_header(self):
        """Should set HX-Refresh header to 'true'."""
        response = htmx_refresh()
        assert response["HX-Refresh"] == "true"


class TestHtmxSuccess:
    """Tests for htmx_success function."""

    def test_basic_success_message(self):
        """Should create success response with toast trigger."""
        response = htmx_success("Item saved!")
        trigger_data = json.loads(response["HX-Trigger"])

        assert "showToast" in trigger_data
        assert trigger_data["showToast"]["type"] == "success"
        assert trigger_data["showToast"]["message"] == "Item saved!"
        assert trigger_data["showToast"]["duration"] == 5000

    def test_success_with_custom_duration(self):
        """Should allow custom duration."""
        response = htmx_success("Quick message", duration=2000)
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["showToast"]["duration"] == 2000

    def test_success_with_title(self):
        """Should include title when provided."""
        response = htmx_success("Details here", title="Success!")
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["showToast"]["title"] == "Success!"

    def test_success_with_action(self):
        """Should include action button config."""
        response = htmx_success(
            "Item deleted",
            action={"label": "Undo", "onClick": "undoDelete()"},
        )
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["showToast"]["action"]["label"] == "Undo"
        assert trigger_data["showToast"]["action"]["onClick"] == "undoDelete()"

    def test_success_with_html_content(self):
        """Should include HTML in response body."""
        response = htmx_success("Done", html="<div>Updated</div>")
        assert response.content == b"<div>Updated</div>"


class TestHtmxError:
    """Tests for htmx_error function."""

    def test_basic_error_message(self):
        """Should create error response with toast trigger."""
        response = htmx_error("Something went wrong")
        trigger_data = json.loads(response["HX-Trigger"])

        assert response.status_code == 400
        assert trigger_data["showToast"]["type"] == "error"
        assert trigger_data["showToast"]["message"] == "Something went wrong"
        assert trigger_data["showToast"]["duration"] == 0  # Persistent by default

    def test_error_with_custom_status(self):
        """Should allow custom HTTP status code."""
        response = htmx_error("Validation failed", status=422)
        assert response.status_code == 422

    def test_error_with_retry_action(self):
        """Should include retry action when requested."""
        response = htmx_error("Server error", show_retry=True)
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["showToast"]["action"]["label"] == "Retry"


class TestHtmxWarning:
    """Tests for htmx_warning function."""

    def test_basic_warning_message(self):
        """Should create warning response with toast trigger."""
        response = htmx_warning("Session expiring soon")
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["showToast"]["type"] == "warning"
        assert trigger_data["showToast"]["message"] == "Session expiring soon"
        assert trigger_data["showToast"]["duration"] == 8000


class TestHtmxModalClose:
    """Tests for htmx_modal_close function."""

    def test_basic_modal_close(self):
        """Should trigger closeModal event."""
        response = htmx_modal_close()
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["closeModal"] is True

    def test_modal_close_with_message(self):
        """Should include success toast when message provided."""
        response = htmx_modal_close(message="Saved successfully!")
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["closeModal"] is True
        assert trigger_data["showToast"]["message"] == "Saved successfully!"

    def test_modal_close_with_refresh(self):
        """Should include refresh section trigger."""
        response = htmx_modal_close(
            message="Done",
            refresh_target="#items-list",
            refresh_url="/items/",
        )
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["refreshSection"]["target"] == "#items-list"
        assert trigger_data["refreshSection"]["url"] == "/items/"


class TestHtmxRefreshSection:
    """Tests for htmx_refresh_section function."""

    def test_sets_retarget_header(self):
        """Should set HX-Retarget header."""
        response = htmx_refresh_section("#my-section", html="<div>New</div>")
        assert response["HX-Retarget"] == "#my-section"
        assert response["HX-Reswap"] == "innerHTML"

    def test_includes_success_message(self):
        """Should include toast when message provided."""
        response = htmx_refresh_section(
            "#my-section",
            html="<div>New</div>",
            message="Section updated",
        )
        trigger_data = json.loads(response["HX-Trigger"])

        assert trigger_data["showToast"]["message"] == "Section updated"


@pytest.mark.django_db
class TestHtmxValidationResponse:
    """Tests for htmx_validation_response function."""

    def test_validation_error_response(self):
        """Should render error template with errors."""
        response = htmx_validation_response(
            "email",
            errors=["Invalid email format"],
        )
        assert response.status_code == 200
        # Response should contain error markup

    def test_validation_success_response(self):
        """Should render success template with message."""
        response = htmx_validation_response(
            "username",
            success_message="Username available",
        )
        assert response.status_code == 200
        # Response should contain success markup

    def test_validation_neutral_response(self):
        """Should render empty success when no errors or message."""
        response = htmx_validation_response("field")
        assert response.status_code == 200
