"""
Behavioral tests for web/exceptions module.

Tests custom exception classes, status codes, error codes, and JSON serialization.
"""

import pytest


class TestWebAPIException:
    """Tests for WebAPIException class."""

    def test_is_exception_subclass(self):
        """WebAPIException is an Exception subclass."""
        from local_deep_research.web.exceptions import WebAPIException

        assert issubclass(WebAPIException, Exception)

    def test_default_status_code_is_500(self):
        """Default status code is 500."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test error")
        assert exc.status_code == 500

    def test_custom_status_code(self):
        """Accepts custom status code."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("not found", status_code=404)
        assert exc.status_code == 404

    def test_message_stored(self):
        """Message is stored as attribute."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("something went wrong")
        assert exc.message == "something went wrong"

    def test_message_in_str(self):
        """Message appears in str representation."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("something went wrong")
        assert str(exc) == "something went wrong"

    def test_default_error_code_is_class_name(self):
        """Default error code is the class name."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test")
        assert exc.error_code == "WebAPIException"

    def test_custom_error_code(self):
        """Accepts custom error code."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test", error_code="CUSTOM_ERROR")
        assert exc.error_code == "CUSTOM_ERROR"

    def test_default_details_is_empty_dict(self):
        """Default details is empty dict."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test")
        assert exc.details == {}

    def test_custom_details(self):
        """Accepts custom details dict."""
        from local_deep_research.web.exceptions import WebAPIException

        details = {"field": "email", "reason": "invalid"}
        exc = WebAPIException("test", details=details)
        assert exc.details == details

    def test_can_be_raised_and_caught(self):
        """Can be raised and caught."""
        from local_deep_research.web.exceptions import WebAPIException

        with pytest.raises(WebAPIException):
            raise WebAPIException("test")


class TestWebAPIExceptionToDict:
    """Tests for WebAPIException.to_dict method."""

    def test_to_dict_has_status_key(self):
        """to_dict includes 'status' key."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test")
        result = exc.to_dict()
        assert result["status"] == "error"

    def test_to_dict_has_message(self):
        """to_dict includes message."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("something failed")
        result = exc.to_dict()
        assert result["message"] == "something failed"

    def test_to_dict_has_error_code(self):
        """to_dict includes error_code."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test", error_code="MY_ERROR")
        result = exc.to_dict()
        assert result["error_code"] == "MY_ERROR"

    def test_to_dict_excludes_empty_details(self):
        """to_dict does not include details when empty."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test")
        result = exc.to_dict()
        assert "details" not in result

    def test_to_dict_includes_details_when_present(self):
        """to_dict includes details when non-empty."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test", details={"key": "value"})
        result = exc.to_dict()
        assert result["details"] == {"key": "value"}

    def test_to_dict_returns_dict(self):
        """to_dict returns a dictionary."""
        from local_deep_research.web.exceptions import WebAPIException

        exc = WebAPIException("test")
        assert isinstance(exc.to_dict(), dict)


class TestAuthenticationRequiredError:
    """Tests for AuthenticationRequiredError class."""

    def test_is_web_api_exception_subclass(self):
        """AuthenticationRequiredError is a WebAPIException subclass."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
            WebAPIException,
        )

        assert issubclass(AuthenticationRequiredError, WebAPIException)

    def test_default_status_code_is_401(self):
        """Default status code is 401."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError()
        assert exc.status_code == 401

    def test_default_message(self):
        """Has a default message about authentication."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError()
        assert "Authentication required" in exc.message

    def test_custom_message(self):
        """Accepts custom message."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError(message="Login expired")
        assert exc.message == "Login expired"

    def test_error_code_is_authentication_required(self):
        """Error code is AUTHENTICATION_REQUIRED."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError()
        assert exc.error_code == "AUTHENTICATION_REQUIRED"

    def test_no_username_means_empty_details(self):
        """No username means empty details."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError()
        assert exc.details == {}

    def test_username_stored_in_details(self):
        """Username is stored in details dict."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError(username="admin")
        assert exc.details["username"] == "admin"

    def test_to_dict_includes_username(self):
        """to_dict includes username in details."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
        )

        exc = AuthenticationRequiredError(username="testuser")
        result = exc.to_dict()
        assert result["details"]["username"] == "testuser"

    def test_can_be_caught_as_web_api_exception(self):
        """Can be caught as WebAPIException."""
        from local_deep_research.web.exceptions import (
            AuthenticationRequiredError,
            WebAPIException,
        )

        with pytest.raises(WebAPIException):
            raise AuthenticationRequiredError()
