"""domain exceptions 单元测试."""

from __future__ import annotations

import pytest
from domain.exceptions import (
    DomainError,
    NotFoundError,
    QuotaExceededError,
    ValidationError,
)


class TestDomainError:
    """DomainError 基类测试."""

    def test_is_exception(self):
        assert issubclass(DomainError, Exception)

    def test_raise_and_catch(self):
        with pytest.raises(DomainError):
            raise DomainError("something went wrong")

    def test_message(self):
        err = DomainError("test message")
        assert str(err) == "test message"

    def test_empty_message(self):
        err = DomainError()
        assert str(err) == ""


class TestNotFoundError:
    """NotFoundError 测试."""

    def test_is_domain_error(self):
        assert issubclass(NotFoundError, DomainError)

    def test_raise_and_catch_as_domain(self):
        with pytest.raises(DomainError):
            raise NotFoundError("user not found")

    def test_raise_and_catch_specific(self):
        with pytest.raises(NotFoundError):
            raise NotFoundError("user not found")

    def test_message(self):
        err = NotFoundError("resource not found")
        assert str(err) == "resource not found"


class TestValidationError:
    """ValidationError 测试."""

    def test_is_domain_error(self):
        assert issubclass(ValidationError, DomainError)

    def test_raise_and_catch_as_domain(self):
        with pytest.raises(DomainError):
            raise ValidationError("invalid input")

    def test_raise_and_catch_specific(self):
        with pytest.raises(ValidationError):
            raise ValidationError("invalid input")

    def test_message(self):
        err = ValidationError("bad data")
        assert str(err) == "bad data"


class TestQuotaExceededError:
    """QuotaExceededError 测试."""

    def test_is_domain_error(self):
        assert issubclass(QuotaExceededError, DomainError)

    def test_constructor_stores_fields(self):
        err = QuotaExceededError("storage", limit=100.0, used=150.0)
        assert err.dimension == "storage"
        assert err.limit == 100.0
        assert err.used == 150.0

    def test_message_format(self):
        err = QuotaExceededError("storage", limit=100.0, used=150.0)
        assert "storage" in str(err)
        assert "150.0" in str(err)
        assert "100.0" in str(err)
        assert "Quota exceeded" in str(err)

    def test_raise_and_catch_as_domain(self):
        with pytest.raises(DomainError):
            raise QuotaExceededError("api_calls", limit=1000, used=2000)

    def test_raise_and_catch_specific(self):
        with pytest.raises(QuotaExceededError):
            raise QuotaExceededError("api_calls", limit=1000, used=2000)

    def test_int_values(self):
        err = QuotaExceededError("count", limit=100, used=150)
        assert err.limit == 100
        assert err.used == 150
        assert "150/100" in str(err)

    def test_float_values(self):
        err = QuotaExceededError("size", limit=10.5, used=20.3)
        assert err.limit == 10.5
        assert err.used == 20.3
