"""Tests for SDK exception hierarchy."""

from dalysdk.exceptions import (
    AuthenticationError,
    ConflictError,
    DalyAPIError,
    ForbiddenError,
    NotFoundError,
    RateLimitError,
    ServerError,
    TimeoutError,
    ValidationError,
)


class TestExceptionHierarchy:
    def test_all_inherit_from_base(self):
        assert issubclass(AuthenticationError, DalyAPIError)
        assert issubclass(ForbiddenError, DalyAPIError)
        assert issubclass(NotFoundError, DalyAPIError)
        assert issubclass(ConflictError, DalyAPIError)
        assert issubclass(ValidationError, DalyAPIError)
        assert issubclass(RateLimitError, DalyAPIError)
        assert issubclass(ServerError, DalyAPIError)
        assert issubclass(TimeoutError, DalyAPIError)

    def test_base_error_attributes(self):
        err = DalyAPIError(500, "Server error", {"detail": "oops"})
        assert err.status_code == 500
        assert err.detail == "Server error"
        assert err.response_body == {"detail": "oops"}
        assert "500" in str(err)

    def test_auth_error_defaults(self):
        err = AuthenticationError()
        assert err.status_code == 401
        assert "Authentication" in err.detail

    def test_forbidden_error_defaults(self):
        err = ForbiddenError()
        assert err.status_code == 403

    def test_not_found_error_defaults(self):
        err = NotFoundError()
        assert err.status_code == 404

    def test_conflict_error_defaults(self):
        err = ConflictError()
        assert err.status_code == 409
        assert "conflict" in err.detail.lower()

    def test_conflict_error_custom_detail(self):
        err = ConflictError(detail="Duplicate name", response_body={"detail": "Duplicate name"})
        assert err.status_code == 409
        assert err.detail == "Duplicate name"
        assert err.response_body == {"detail": "Duplicate name"}

    def test_validation_error_preserves_status(self):
        err = ValidationError(422, "Invalid input")
        assert err.status_code == 422

    def test_rate_limit_error_defaults(self):
        err = RateLimitError()
        assert err.status_code == 429
        assert "rate limit" in err.detail.lower()
        assert err.retry_after is None

    def test_rate_limit_error_with_retry_after(self):
        err = RateLimitError(retry_after=30.0)
        assert err.status_code == 429
        assert err.retry_after == 30.0

    def test_rate_limit_error_custom_detail(self):
        err = RateLimitError(detail="Too many requests", response_body={"detail": "slow down"}, retry_after=60)
        assert err.detail == "Too many requests"
        assert err.response_body == {"detail": "slow down"}
        assert err.retry_after == 60

    def test_server_error_custom_status(self):
        err = ServerError(503, "Service unavailable")
        assert err.status_code == 503

    def test_timeout_error_defaults(self):
        err = TimeoutError()
        assert err.status_code == 0
        assert "timed out" in err.detail.lower()
        assert err.response_body is None

    def test_timeout_error_custom_detail(self):
        err = TimeoutError(detail="Request timed out: GET /locations")
        assert err.detail == "Request timed out: GET /locations"

    def test_all_catchable_as_base(self):
        """All SDK exceptions can be caught with a single except DalyAPIError."""
        exceptions = [
            AuthenticationError(),
            ForbiddenError(),
            NotFoundError(),
            ConflictError(),
            ValidationError(422, "bad"),
            RateLimitError(),
            ServerError(500),
            TimeoutError(),
        ]
        for exc in exceptions:
            try:
                raise exc
            except DalyAPIError:
                pass  # Expected — all should be caught here
