"""
Test cases for news API exception handling.
"""

from local_deep_research.news.exceptions import (
    NewsAPIException,
    InvalidLimitException,
    SubscriptionNotFoundException,
    SubscriptionCreationException,
    SubscriptionUpdateException,
    SubscriptionDeletionException,
    DatabaseAccessException,
    NewsFeedGenerationException,
    ResearchProcessingException,
    NotImplementedException,
    InvalidParameterException,
    SchedulerNotificationException,
)


class TestNewsAPIException:
    """Test the base NewsAPIException class."""

    def test_basic_exception(self):
        """Test basic exception creation."""
        exc = NewsAPIException("Test error", status_code=400)

        assert str(exc) == "Test error"
        assert exc.message == "Test error"
        assert exc.status_code == 400
        assert exc.error_code == "NewsAPIException"
        assert exc.details == {}

    def test_exception_with_details(self):
        """Test exception with additional details."""
        details = {"key": "value", "count": 42}
        exc = NewsAPIException(
            "Test error",
            status_code=500,
            error_code="CUSTOM_ERROR",
            details=details,
        )

        assert exc.error_code == "CUSTOM_ERROR"
        assert exc.details == details

    def test_to_dict(self):
        """Test converting exception to dictionary."""
        exc = NewsAPIException(
            "Test error",
            status_code=403,
            error_code="TEST_ERROR",
            details={"user": "test"},
        )

        result = exc.to_dict()

        assert result == {
            "error": "Test error",
            "error_code": "TEST_ERROR",
            "status_code": 403,
            "details": {"user": "test"},
        }

    def test_to_dict_without_details(self):
        """Test converting exception without details."""
        exc = NewsAPIException("Simple error")
        result = exc.to_dict()

        assert result == {
            "error": "Simple error",
            "error_code": "NewsAPIException",
            "status_code": 500,
        }


class TestSpecificExceptions:
    """Test specific exception subclasses."""

    def test_invalid_limit_exception(self):
        """Test InvalidLimitException."""
        exc = InvalidLimitException(-5)

        assert exc.status_code == 400
        assert exc.error_code == "INVALID_LIMIT"
        assert "-5" in exc.message
        assert exc.details["provided_limit"] == -5
        assert exc.details["min_limit"] == 1

    def test_subscription_not_found(self):
        """Test SubscriptionNotFoundException."""
        exc = SubscriptionNotFoundException("sub-123")

        assert exc.status_code == 404
        assert exc.error_code == "SUBSCRIPTION_NOT_FOUND"
        assert "sub-123" in exc.message
        assert exc.details["subscription_id"] == "sub-123"

    def test_subscription_creation_exception(self):
        """Test SubscriptionCreationException."""
        exc = SubscriptionCreationException(
            "Database error", {"query": "test query", "type": "search"}
        )

        assert exc.status_code == 500
        assert exc.error_code == "SUBSCRIPTION_CREATE_FAILED"
        assert "Database error" in exc.message
        assert exc.details["query"] == "test query"

    def test_subscription_update_exception(self):
        """Test SubscriptionUpdateException."""
        exc = SubscriptionUpdateException("sub-456", "Invalid data")

        assert exc.status_code == 500
        assert exc.error_code == "SUBSCRIPTION_UPDATE_FAILED"
        assert "sub-456" in exc.message
        assert "Invalid data" in exc.message
        assert exc.details["subscription_id"] == "sub-456"

    def test_subscription_deletion_exception(self):
        """Test SubscriptionDeletionException."""
        exc = SubscriptionDeletionException("sub-789", "Permission denied")

        assert exc.status_code == 500
        assert exc.error_code == "SUBSCRIPTION_DELETE_FAILED"
        assert "sub-789" in exc.message
        assert "Permission denied" in exc.message
        assert exc.details["subscription_id"] == "sub-789"

    def test_database_access_exception(self):
        """Test DatabaseAccessException."""
        exc = DatabaseAccessException("query_operation", "Connection lost")

        assert exc.status_code == 500
        assert exc.error_code == "DATABASE_ERROR"
        assert "query_operation" in exc.message
        assert "Connection lost" in exc.message
        assert exc.details["operation"] == "query_operation"

    def test_news_feed_generation_exception(self):
        """Test NewsFeedGenerationException."""
        exc = NewsFeedGenerationException("Processing error", user_id="user123")

        assert exc.status_code == 500
        assert exc.error_code == "FEED_GENERATION_FAILED"
        assert "Processing error" in exc.message
        assert exc.details["user_id"] == "user123"

    def test_news_feed_generation_without_user(self):
        """Test NewsFeedGenerationException without user_id."""
        exc = NewsFeedGenerationException("Processing error")

        assert exc.details == {}

    def test_research_processing_exception(self):
        """Test ResearchProcessingException."""
        exc = ResearchProcessingException(
            "Parse error", research_id="research-001"
        )

        assert exc.status_code == 500
        assert exc.error_code == "RESEARCH_PROCESSING_FAILED"
        assert "Parse error" in exc.message
        assert exc.details["research_id"] == "research-001"

    def test_not_implemented_exception(self):
        """Test NotImplementedException."""
        exc = NotImplementedException("advanced_search")

        assert exc.status_code == 501
        assert exc.error_code == "NOT_IMPLEMENTED"
        assert "advanced_search" in exc.message
        assert exc.details["feature"] == "advanced_search"

    def test_invalid_parameter_exception(self):
        """Test InvalidParameterException."""
        exc = InvalidParameterException(
            "refresh_interval", -100, "Must be positive"
        )

        assert exc.status_code == 400
        assert exc.error_code == "INVALID_PARAMETER"
        assert "refresh_interval" in exc.message
        assert "Must be positive" in exc.message
        assert exc.details["parameter"] == "refresh_interval"
        assert exc.details["value"] == -100

    def test_scheduler_notification_exception(self):
        """Test SchedulerNotificationException."""
        exc = SchedulerNotificationException("update", "Service unavailable")

        assert exc.status_code == 500
        assert exc.error_code == "SCHEDULER_NOTIFICATION_FAILED"
        assert "update" in exc.message
        assert "Service unavailable" in exc.message
        assert exc.details["action"] == "update"
