"""Tests for delivery functionality in HAX SDK."""

from unittest.mock import MagicMock, patch

from hax import HaxClient
from hax.models.delivery import DeliveryConfig, DeliveryResult


class TestDeliveryConfig:
    """Tests for DeliveryConfig model."""

    def test_email_delivery_config(self) -> None:
        config = DeliveryConfig(
            channel="email",
            recipient="user@example.com",
            subject="Test Subject",
            message="Custom message",
        )
        assert config.channel == "email"
        assert config.recipient == "user@example.com"
        assert config.subject == "Test Subject"
        assert config.message == "Custom message"

    def test_sms_delivery_config(self) -> None:
        config = DeliveryConfig(
            channel="sms",
            recipient="+15551234567",
            message="Custom SMS",
        )
        assert config.channel == "sms"
        assert config.recipient == "+15551234567"
        assert config.subject is None  # SMS doesn't use subject

    def test_minimal_delivery_config(self) -> None:
        config = DeliveryConfig(
            channel="email",
            recipient="test@example.com",
        )
        assert config.channel == "email"
        assert config.subject is None
        assert config.message is None


class TestDeliveryResult:
    """Tests for DeliveryResult model."""

    def test_successful_result(self) -> None:
        result = DeliveryResult(
            success=True,
            channel="email",
        )
        assert result.success is True
        assert result.channel == "email"
        assert result.error is None

    def test_failed_result(self) -> None:
        result = DeliveryResult(
            success=False,
            channel="sms",
            error="Invalid phone number",
        )
        assert result.success is False
        assert result.error == "Invalid phone number"


class TestClientDeliveryMethods:
    """Tests for HaxClient delivery methods."""

    @patch("hax.http.HttpClient.post")
    def test_create_request_with_email_delivery(self, mock_post: MagicMock) -> None:
        mock_post.return_value = {
            "id": "req_123",
            "url": "https://hax.example.com/hub/r/req_123",
            "type": "confirm-action-v1",
            "title": None,
            "description": None,
            "payload": {"title": "Test"},
            "metadata": {},
            "webhookUrl": None,
            "status": "pending",
            "createdAt": "2024-01-15T10:00:00Z",
            "expiresAt": None,
            "delivery": {"success": True, "channel": "email"},
        }

        client = HaxClient(api_key="test_key")
        request = client.create_request(
            type="confirm-action-v1",
            payload={"title": "Test"},
            delivery=DeliveryConfig(channel="email", recipient="test@example.com"),
        )

        assert request.id == "req_123"
        assert request.url == "https://hax.example.com/hub/r/req_123"
        assert request.delivery is not None
        assert request.delivery.success is True
        assert request.delivery.channel == "email"

        # Verify delivery was included in API call
        call_args = mock_post.call_args
        assert call_args[1]["json"]["delivery"]["channel"] == "email"
        assert call_args[1]["json"]["delivery"]["recipient"] == "test@example.com"

    @patch("hax.http.HttpClient.post")
    def test_request_via_email_convenience_method(self, mock_post: MagicMock) -> None:
        mock_post.return_value = {
            "id": "req_123",
            "url": "https://hax.example.com/hub/r/req_123",
            "type": "confirm-action-v1",
            "title": None,
            "description": None,
            "payload": {"title": "Test"},
            "metadata": {},
            "webhookUrl": None,
            "status": "pending",
            "createdAt": "2024-01-15T10:00:00Z",
            "expiresAt": None,
            "delivery": {"success": True, "channel": "email"},
        }

        client = HaxClient(api_key="test_key")
        request = client.request_via_email(
            type="confirm-action-v1",
            payload={"title": "Test"},
            to_email="user@example.com",
            subject="Custom Subject",
        )

        assert request.delivery is not None
        assert request.delivery.success is True

        call_args = mock_post.call_args
        assert call_args[1]["json"]["delivery"]["channel"] == "email"
        assert call_args[1]["json"]["delivery"]["recipient"] == "user@example.com"
        assert call_args[1]["json"]["delivery"]["subject"] == "Custom Subject"

    @patch("hax.http.HttpClient.post")
    def test_request_via_sms_convenience_method(self, mock_post: MagicMock) -> None:
        mock_post.return_value = {
            "id": "req_123",
            "url": "https://hax.example.com/hub/r/req_123",
            "type": "confirm-action-v1",
            "title": None,
            "description": None,
            "payload": {"title": "Test"},
            "metadata": {},
            "webhookUrl": None,
            "status": "pending",
            "createdAt": "2024-01-15T10:00:00Z",
            "expiresAt": None,
            "delivery": {"success": True, "channel": "sms"},
        }

        client = HaxClient(api_key="test_key")
        request = client.request_via_sms(
            type="confirm-action-v1",
            payload={"title": "Test"},
            to_phone="+15551234567",
        )

        assert request.delivery is not None
        assert request.delivery.channel == "sms"

        call_args = mock_post.call_args
        assert call_args[1]["json"]["delivery"]["channel"] == "sms"
        assert call_args[1]["json"]["delivery"]["recipient"] == "+15551234567"

    @patch("hax.http.HttpClient.post")
    def test_request_without_delivery_returns_url(self, mock_post: MagicMock) -> None:
        """URL is always returned even without delivery."""
        mock_post.return_value = {
            "id": "req_123",
            "url": "https://hax.example.com/hub/r/req_123",
            "type": "confirm-action-v1",
            "title": None,
            "description": None,
            "payload": {"title": "Test"},
            "metadata": {},
            "webhookUrl": None,
            "status": "pending",
            "createdAt": "2024-01-15T10:00:00Z",
            "expiresAt": None,
            "delivery": None,
        }

        client = HaxClient(api_key="test_key")
        request = client.create_request(
            type="confirm-action-v1",
            payload={"title": "Test"},
        )

        assert request.url == "https://hax.example.com/hub/r/req_123"
        assert request.delivery is None

    @patch("hax.http.HttpClient.post")
    def test_delivery_failure_still_returns_request(self, mock_post: MagicMock) -> None:
        """Request is created even if delivery fails."""
        mock_post.return_value = {
            "id": "req_123",
            "url": "https://hax.example.com/hub/r/req_123",
            "type": "confirm-action-v1",
            "title": None,
            "description": None,
            "payload": {"title": "Test"},
            "metadata": {},
            "webhookUrl": None,
            "status": "pending",
            "createdAt": "2024-01-15T10:00:00Z",
            "expiresAt": None,
            "delivery": {
                "success": False,
                "channel": "email",
                "error": "Invalid email address",
            },
        }

        client = HaxClient(api_key="test_key")
        request = client.request_via_email(
            type="confirm-action-v1",
            payload={"title": "Test"},
            to_email="invalid",
        )

        assert request.id == "req_123"
        assert request.url is not None
        assert request.delivery is not None
        assert request.delivery.success is False
        assert request.delivery.error is not None
        assert "Invalid email" in request.delivery.error


class TestConfigureMessaging:
    """Tests for configure_messaging method."""

    @patch("hax.http.HttpClient.patch")
    def test_configure_email_provider(self, mock_patch: MagicMock) -> None:
        mock_patch.return_value = {"success": True}

        client = HaxClient(api_key="test_key")
        client.configure_messaging(
            email={
                "provider": "sendgrid",
                "apiKey": "SG.xxx",
                "fromEmail": "noreply@example.com",
            }
        )

        call_args = mock_patch.call_args
        assert "messaging" in call_args[1]["json"]
        assert call_args[1]["json"]["messaging"]["email"]["provider"] == "sendgrid"

    @patch("hax.http.HttpClient.patch")
    def test_configure_sms_provider(self, mock_patch: MagicMock) -> None:
        mock_patch.return_value = {"success": True}

        client = HaxClient(api_key="test_key")
        client.configure_messaging(
            sms={
                "provider": "twilio",
                "accountSid": "ACxxx",
                "authToken": "xxx",
                "fromNumber": "+15551234567",
            }
        )

        call_args = mock_patch.call_args
        assert call_args[1]["json"]["messaging"]["sms"]["provider"] == "twilio"

    @patch("hax.http.HttpClient.patch")
    def test_configure_both_providers(self, mock_patch: MagicMock) -> None:
        mock_patch.return_value = {"success": True}

        client = HaxClient(api_key="test_key")
        client.configure_messaging(
            email={
                "provider": "sendgrid",
                "apiKey": "SG.xxx",
                "fromEmail": "noreply@example.com",
            },
            sms={
                "provider": "twilio",
                "accountSid": "ACxxx",
                "authToken": "xxx",
                "fromNumber": "+15551234567",
            },
        )

        call_args = mock_patch.call_args
        messaging = call_args[1]["json"]["messaging"]
        assert "email" in messaging
        assert "sms" in messaging
