"""
Tests für Re-Exports des Umbrella-Pakets.

Validiert, dass:
1. Alle Symbole aus __all__ importierbar sind
2. Die re-exportierten Symbole die korrekten Typen haben
3. Keine fehlenden oder überflüssigen Exports existieren
"""

import inspect

import questra


class TestReExports:
    """Tests für Re-Export Validierung."""

    def test_all_symbols_are_importable(self):
        """Test: Alle in __all__ deklarierten Symbole sind importierbar."""
        for symbol_name in questra.__all__:
            assert hasattr(questra, symbol_name), (
                f"Symbol '{symbol_name}' ist in __all__ definiert, "
                f"aber nicht importierbar"
            )

    def test_all_imports_match_module_exports(self):
        """Test: __all__ enthält alle öffentlichen Exports (keine privaten)."""
        # Alle öffentlichen Symbole im Modul
        public_symbols = {
            name
            for name in dir(questra)
            if not name.startswith("_")
            and name
            not in [
                "questra_authentication",
                "questra_data",
            ]  # Sub-Module selbst nicht exportieren
        }

        # __all__ sollte alle öffentlichen Symbole enthalten (oder gezielt auslassen)
        all_set = set(questra.__all__)

        # __version__ ist öffentlich aber nicht in __all__ (OK)
        allowed_public_not_in_all = {"__version__"}

        missing_in_all = public_symbols - all_set - allowed_public_not_in_all

        assert not missing_in_all, (
            f"Öffentliche Symbole fehlen in __all__: {missing_in_all}"
        )

    def test_no_undefined_symbols_in_all(self):
        """Test: Keine undefinierten Symbole in __all__."""
        undefined = [name for name in questra.__all__ if not hasattr(questra, name)]

        assert not undefined, f"Undefinierte Symbole in __all__: {undefined}"

    def test_main_classes_are_correct_types(self):
        """Test: Hauptklassen haben die erwarteten Typen."""
        # Authentication
        assert inspect.isclass(questra.QuestraAuthentication)
        assert inspect.isclass(questra.OAuth2Authentication)
        assert inspect.isclass(questra.OAuth2ServiceCredential)
        assert inspect.isclass(questra.OAuth2InteractiveUserCredential)

        # Data
        assert inspect.isclass(questra.QuestraData)
        assert inspect.isclass(questra.QuestraDataCore)

        # Models
        assert inspect.isclass(questra.Inventory)
        assert inspect.isclass(questra.Namespace)

    def test_exceptions_are_correct_types(self):
        """Test: Exception-Klassen sind tatsächlich Exceptions."""
        exception_classes = [
            "AuthenticationError",
            "NotAuthenticatedError",
            "SessionNotInitializedError",
            "InvalidCredentialsError",
            "TokenExpiredError",
            "OidcDiscoveryError",
            "QuestraAuthenticationError",
            "QuestraError",
            "QuestraGraphQLError",
        ]

        for exc_name in exception_classes:
            exc_class = getattr(questra, exc_name)
            assert inspect.isclass(exc_class)
            assert issubclass(exc_class, Exception), (
                f"{exc_name} ist keine Exception-Klasse"
            )


class TestImportPaths:
    """Tests für Import-Pfade und Namespaces."""

    def test_direct_import_from_questra(self):
        """Test: Direkte Imports von questra funktionieren."""
        from questra import QuestraAuthentication, QuestraData

        assert QuestraAuthentication is not None
        assert QuestraData is not None

    def test_selective_import_from_questra(self):
        """Test: Selektive Imports funktionieren."""
        from questra import (
            Inventory,
            Namespace,
            OAuth2Authentication,
            QuestraData,
        )

        assert OAuth2Authentication is not None
        assert QuestraData is not None
        assert Inventory is not None
        assert Namespace is not None

    def test_star_import_works(self):
        """Test: Star-Import funktioniert (obwohl nicht empfohlen)."""
        import questra

        # Simuliere: from questra import *
        namespace = {}
        for name in questra.__all__:
            namespace[name] = getattr(questra, name)

        assert "QuestraAuthentication" in namespace
        assert "QuestraData" in namespace
        assert len(namespace) == len(questra.__all__)


class TestVersionAttribute:
    """Tests für Version-Attribut."""

    def test_version_exists(self):
        """Test: __version__ Attribut existiert."""
        assert hasattr(questra, "__version__")

    def test_version_format(self):
        """Test: __version__ hat korrektes Format (semver)."""
        version = questra.__version__
        assert isinstance(version, str)

        # Einfache Semver-Validierung: x.y.z
        parts = version.split(".")
        assert len(parts) >= 2, f"Version '{version}' ist kein gültiges Semver-Format"

        # Erste zwei Teile sollten Zahlen sein
        assert parts[0].isdigit(), f"Major-Version ist keine Zahl: {parts[0]}"
        assert parts[1].isdigit(), f"Minor-Version ist keine Zahl: {parts[1]}"


class TestEnumExports:
    """Tests für Enum-Exports."""

    def test_enums_are_importable(self):
        """Test: Alle Enums sind importierbar und haben erwartete Values."""
        from questra import (
            Aggregation,
            ConflictAction,
            DataType,
            InventoryType,
            PermissionState,
            Quality,
            RelationType,
            SortOrder,
        )

        # Prüfe, dass es Enum-ähnliche Objekte sind (haben .name, .value)
        assert hasattr(SortOrder, "__members__")
        assert hasattr(ConflictAction, "__members__")
        assert hasattr(RelationType, "__members__")
        assert hasattr(DataType, "__members__")
        assert hasattr(InventoryType, "__members__")
        assert hasattr(Aggregation, "__members__")
        assert hasattr(Quality, "__members__")
        assert hasattr(PermissionState, "__members__")


class TestPropertyHelpers:
    """Tests für Property Helper Klassen."""

    def test_property_helpers_are_classes(self):
        """Test: Property Helper Klassen sind importierbar."""
        from questra import (
            BoolProperty,
            DateProperty,
            DateTimeOffsetProperty,
            DateTimeProperty,
            DecimalProperty,
            FileProperty,
            GuidProperty,
            IntProperty,
            LongProperty,
            StringProperty,
            TimeProperty,
            TimeSeriesProperty,
        )

        property_classes = [
            StringProperty,
            IntProperty,
            LongProperty,
            DecimalProperty,
            BoolProperty,
            DateTimeProperty,
            DateTimeOffsetProperty,
            DateProperty,
            TimeProperty,
            GuidProperty,
            FileProperty,
            TimeSeriesProperty,
        ]

        for prop_class in property_classes:
            assert inspect.isclass(prop_class)
