"""Tests for neonlink.errors."""

from neonlink.errors import (
    CircuitBreakerOpenError,
    ErrorClass,
    PayloadTooLargeError,
    PermanentError,
    classify,
    is_permanent,
    is_transient,
)


class TestClassify:
    def test_none(self):
        # classify(None) should return UNKNOWN
        assert classify(None) == ErrorClass.UNKNOWN

    def test_permanent_error(self):
        err = PermanentError(ValueError("bad input"))
        assert classify(err) == ErrorClass.PERMANENT
        assert is_permanent(err)
        assert not is_transient(err)

    def test_permanent_error_string(self):
        err = PermanentError("bad schema")
        assert classify(err) == ErrorClass.PERMANENT
        assert "permanent: bad schema" in str(err)

    def test_permanent_error_none(self):
        err = PermanentError()
        assert str(err) == "permanent error"

    def test_payload_too_large(self):
        err = PayloadTooLargeError("1MB exceeded")
        assert classify(err) == ErrorClass.PERMANENT

    def test_permanent_keywords(self):
        keywords = [
            "validation failed", "invalid input", "schema mismatch",
            "constraint violation", "auth denied", "forbidden access",
            "permission denied", "malformed request", "syntax error",
        ]
        for kw in keywords:
            err = Exception(kw)
            assert classify(err) == ErrorClass.PERMANENT, f"expected PERMANENT for {kw!r}"

    def test_transient_keywords(self):
        keywords = [
            "connection refused", "network unreachable", "timeout exceeded",
            "temporary failure", "rate limited", "overloaded",
            "broker busy", "service unavailable", "retry later",
        ]
        for kw in keywords:
            err = Exception(kw)
            assert classify(err) == ErrorClass.TRANSIENT, f"expected TRANSIENT for {kw!r}"

    def test_unknown(self):
        err = Exception("something happened")
        assert classify(err) == ErrorClass.UNKNOWN

    def test_circuit_breaker_open_error(self):
        err = CircuitBreakerOpenError("open")
        # Not classified as permanent or transient by keywords
        assert classify(err) is not None


class TestErrorClassString:
    def test_values(self):
        assert ErrorClass.TRANSIENT.value == "TRANSIENT"
        assert ErrorClass.PERMANENT.value == "PERMANENT"
        assert ErrorClass.UNKNOWN.value == "UNKNOWN"
