# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import datafusion
import datafusion.functions
import datafusion.object_store
import datafusion.substrait
import pytest

# EnumType introduced in 3.11. 3.10 and prior it was called EnumMeta.
try:
    from enum import EnumType
except ImportError:
    from enum import EnumMeta as EnumType


def _check_enum_exports(internal_obj, wrapped_obj) -> None:
    """Check that all enum values are present in wrapped object."""
    expected_values = [v for v in dir(internal_obj) if not v.startswith("__")]
    for value in expected_values:
        assert value in dir(wrapped_obj)


def _check_list_attribute(internal_attr, wrapped_attr) -> None:
    """Check that list attributes match between internal and wrapped objects."""
    assert isinstance(wrapped_attr, list)

    # We have cases like __all__ that are a list and we want to be certain that
    # every value in the list in the internal object is also in the wrapper list
    for val in internal_attr:
        if isinstance(val, str) and val.startswith("Raw"):
            assert val[3:] in wrapped_attr
        else:
            assert val in wrapped_attr


def missing_exports(internal_obj, wrapped_obj) -> None:
    """
    Identify if any of the rust exposted structs or functions do not have wrappers.

    Special handling for:
    - Raw* classes: Internal implementation details that shouldn't be exposed
    - _global_ctx: Internal implementation detail
    - __self__, __class__, __repr__: Python special attributes
    """
    # Special case enums - EnumType overrides a some of the internal functions,
    # so check all of the values exist and move on
    if isinstance(wrapped_obj, EnumType):
        _check_enum_exports(internal_obj, wrapped_obj)
        return

    if "__repr__" in internal_obj.__dict__ and "__repr__" not in wrapped_obj.__dict__:
        pytest.fail(f"Missing __repr__: {internal_obj.__name__}")

    for internal_attr_name in dir(internal_obj):
        # Single-underscore names are private support methods for the
        # wrappers (e.g. SessionContext._install_extensions) and are not
        # part of the public surface that requires a wrapper.
        if internal_attr_name.startswith("_") and not internal_attr_name.startswith(
            "__"
        ):
            continue

        wrapped_attr_name = internal_attr_name.removeprefix("Raw")

        assert wrapped_attr_name in dir(wrapped_obj)

        internal_attr = getattr(internal_obj, internal_attr_name)
        wrapped_attr = getattr(wrapped_obj, wrapped_attr_name)

        # There are some auto generated attributes that can be None, such as
        # __kwdefaults__ and __doc__. As long as these are None on the internal
        # object, it's okay to skip them. However if they do exist on the internal
        # object they must also exist on the wrapped object.
        if internal_attr is not None and wrapped_attr is None:
            pytest.fail(f"Missing attribute: {internal_attr_name}")

        if internal_attr_name in ["__self__", "__class__"]:
            continue

        if isinstance(internal_attr, list):
            _check_list_attribute(internal_attr, wrapped_attr)
        elif hasattr(internal_attr, "__dict__"):
            # Check all submodules recursively
            missing_exports(internal_attr, wrapped_attr)


def test_datafusion_missing_exports() -> None:
    """Check for any missing python exports.

    This test verifies that every exposed class, attribute,
    and function in the internal (pyo3) module - datafusion._internal
    is also exposed in our python wrappers - datafusion -
    i.e., the ones exposed to the public.
    """
    missing_exports(datafusion._internal, datafusion)
