# 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


# Internal methods a wrapper calls but does not re-export. Add to this only
# when the method exists to serve a public wrapper, never to silence a genuine
# gap in coverage.
PRIVATE_SUPPORT_METHODS = frozenset(
    {
        # The two steps of SessionContext.with_extensions: install the
        # codecs, then run the planner hooks and commit everything the
        # bundles declared.
        "_install_extension_codecs",
        "_commit_extensions",
        # Physical optimizer rules import their capsules in a separate step,
        # so the call can still fail without leaving the session
        # half-installed; the commit itself is a `_commit_extensions`
        # parameter.
        "_resolve_extension_physical_optimizer_rules",
    }
)


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):
        # Private support methods that exist only for a wrapper to call, so
        # they are not part of the public surface and need no wrapper of their
        # own. Listed rather than matched by leading underscore, which would
        # also excuse names like `_repr_html_` that a wrapper does have to
        # provide.
        if internal_attr_name in PRIVATE_SUPPORT_METHODS:
            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)
