"""
Tests for django_stripe_billing.webhooks.

Covers HandlerRegistry and TransientWebhookError.
"""
import pytest

from django_stripe_billing.webhooks import (
    HandlerRegistry,
    TransientWebhookError,
    registry,
)


class TestTransientWebhookError:
    """TransientWebhookError is a distinct exception for retryable failures."""

    def test_is_exception(self):
        exc = TransientWebhookError("temporary failure")
        assert isinstance(exc, Exception)
        assert "temporary failure" in str(exc)


class TestHandlerRegistry:
    """HandlerRegistry maps event types to handlers."""

    def test_get_returns_none_for_unregistered_type(self):
        reg = HandlerRegistry()
        assert reg.get("unknown.event") is None

    def test_register_and_get(self):
        reg = HandlerRegistry()
        def my_handler(data):
            pass
        reg.register("invoice.payment_succeeded", my_handler)
        assert reg.get("invoice.payment_succeeded") is my_handler

    def test_handler_decorator_registers(self):
        reg = HandlerRegistry()
        @reg.handler("custom.event")
        def custom_handler(data):
            return data.get("id")
        assert reg.get("custom.event") is custom_handler

    def test_dispatch_calls_handler_with_data_object(self):
        reg = HandlerRegistry()
        received = []
        @reg.handler("test.event")
        def handler(data_object):
            received.append(data_object)
        reg.dispatch("test.event", {"id": "obj_123", "amount": 1000})
        assert len(received) == 1
        assert received[0]["id"] == "obj_123"
        assert received[0]["amount"] == 1000

    def test_dispatch_raises_key_error_when_no_handler(self):
        reg = HandlerRegistry()
        with pytest.raises(KeyError) as exc_info:
            reg.dispatch("unknown.event", {})
        assert "unknown.event" in str(exc_info.value)

    def test_dispatch_propagates_transient_webhook_error(self):
        reg = HandlerRegistry()
        @reg.handler("test.transient")
        def handler(data_object):
            raise TransientWebhookError("retry me")
        with pytest.raises(TransientWebhookError) as exc_info:
            reg.dispatch("test.transient", {})
        assert "retry me" in str(exc_info.value)


class TestBuiltinRegistry:
    """Global registry has built-in handlers for known event types."""

    def test_has_handler_for_invoice_payment_succeeded(self):
        assert registry.get("invoice.payment_succeeded") is not None

    def test_has_handler_for_checkout_session_completed(self):
        assert registry.get("checkout.session.completed") is not None

    def test_has_handler_for_customer_subscription_deleted(self):
        assert registry.get("customer.subscription.deleted") is not None

    def test_unknown_event_type_returns_none(self):
        assert registry.get("nonexistent.event.type") is None
