from __future__ import annotations

import warnings

import fuggers_py.data as data

from fuggers_py.data import (
    AlreadyExistsError,
    ConnectionFailureError,
    InvalidInputError,
    PermissionDeniedError,
    TraitError,
    TraitIOError,
    TraitTimeoutError,
)
from fuggers_py.data.error import TraitError as LegacyTraitError
from fuggers_py.data.errors import TraitError as CanonicalTraitError


def test_trait_error_subclasses_expose_codes_and_messages() -> None:
    connection = ConnectionFailureError()
    duplicate = AlreadyExistsError("curve already stored")
    invalid = InvalidInputError()

    assert isinstance(connection, TraitError)
    assert connection.code == "connection_failure"
    assert str(connection) == "Connection failure."
    assert duplicate.code == "already_exists"
    assert str(duplicate) == "curve already stored"
    assert invalid.code == "invalid_input"


def test_explicit_error_names_keep_specific_types() -> None:
    permission = PermissionDeniedError()
    timeout = TraitTimeoutError()
    io_error = TraitIOError()

    assert isinstance(permission, PermissionDeniedError)
    assert permission.code == "permission"
    assert timeout.code == "timeout"
    assert io_error.code == "io"


def test_canonical_plural_error_module_keeps_legacy_import_path_working() -> None:
    assert LegacyTraitError is CanonicalTraitError


def test_deprecated_builtin_shadowing_aliases_warn_but_still_resolve() -> None:
    with warnings.catch_warnings(record=True) as caught:
        warnings.simplefilter("always")
        timeout_error = data.TimeoutError
        io_error = data.IOError
        permission_error = data.PermissionError

    assert timeout_error is TraitTimeoutError
    assert io_error is TraitIOError
    assert permission_error is PermissionDeniedError
    assert [str(item.message) for item in caught] == [
        "`fuggers_py.data.TimeoutError` is deprecated; use `TraitTimeoutError`.",
        "`fuggers_py.data.IOError` is deprecated; use `TraitIOError`.",
        "`fuggers_py.data.PermissionError` is deprecated; use `PermissionDeniedError`.",
    ]
    assert "TimeoutError" not in data.__all__
    assert "IOError" not in data.__all__
    assert "PermissionError" not in data.__all__
