# 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 pytest
from datafusion import (
    AggregateUDF,
    DataFrame,
    ScalarUDF,
    SessionContext,
    TableProviderFactory,
    TableProviderFactoryExportable,
    Worker,
    WorkerQueryContext,
    WorkerResolver,
    functions,
)
from datafusion.common import (
    DFSchema,
)
from datafusion.expr import (
    Aggregate,
    AggregateFunction,
    Alias,
    Analyze,
    Between,
    BinaryExpr,
    Case,
    Cast,
    Column,
    CreateMemoryTable,
    CreateView,
    Distinct,
    DropTable,
    Exists,
    Explain,
    Expr,
    Extension,
    Filter,
    GroupingSet,
    HigherOrderFunction,
    ILike,
    InList,
    InSubquery,
    IsFalse,
    IsNotFalse,
    IsNotNull,
    IsNotTrue,
    IsNotUnknown,
    IsTrue,
    IsUnknown,
    Join,
    JoinConstraint,
    JoinType,
    Lambda,
    LambdaVariable,
    Like,
    Limit,
    Literal,
    Negative,
    Not,
    Partitioning,
    Placeholder,
    Projection,
    Repartition,
    ScalarSubquery,
    ScalarVariable,
    SimilarTo,
    Sort,
    Subquery,
    SubqueryAlias,
    TableScan,
    TryCast,
    Union,
)


def test_import_datafusion():
    assert datafusion.__name__ == "datafusion"


def test_datafusion_python_version():
    assert datafusion.__version__ is not None


def test_class_module_is_datafusion():
    # context
    for klass in [
        SessionContext,
        WorkerResolver,
    ]:
        assert klass.__module__ == "datafusion.context"

    # distributed
    for klass in [
        Worker,
        WorkerQueryContext,
    ]:
        assert klass.__module__ == "datafusion.distributed"

    # dataframe
    for klass in [
        DataFrame,
    ]:
        assert klass.__module__ == "datafusion.dataframe"

    # udf
    for klass in [
        AggregateUDF,
        ScalarUDF,
    ]:
        assert klass.__module__ == "datafusion.user_defined"

    # expressions
    for klass in [Expr, Column, Literal, BinaryExpr, AggregateFunction]:
        assert klass.__module__ == "datafusion.expr"

    # operators
    for klass in [
        Projection,
        TableScan,
        Aggregate,
        Sort,
        Limit,
        Filter,
        Analyze,
        Join,
        JoinType,
        JoinConstraint,
        Union,
        Like,
        ILike,
        SimilarTo,
        ScalarVariable,
        Alias,
        Not,
        IsNotNull,
        IsTrue,
        IsFalse,
        IsUnknown,
        IsNotTrue,
        IsNotFalse,
        IsNotUnknown,
        Negative,
        InList,
        Exists,
        Subquery,
        InSubquery,
        ScalarSubquery,
        GroupingSet,
        Placeholder,
        Case,
        Cast,
        TryCast,
        Between,
        SubqueryAlias,
        Explain,
        Extension,
        CreateMemoryTable,
        CreateView,
        Distinct,
        DropTable,
        Repartition,
        Partitioning,
        HigherOrderFunction,
        Lambda,
        LambdaVariable,
    ]:
        assert klass.__module__ == "datafusion.expr"

    # catalog factory types (re-exported at top level)
    for klass in [TableProviderFactory, TableProviderFactoryExportable]:
        assert klass.__module__ == "datafusion.catalog"

    # schema
    for klass in [DFSchema]:
        assert klass.__module__ == "datafusion.common"


def test_import_from_functions_submodule():
    from datafusion.functions import abs as df_abs
    from datafusion.functions import sin

    assert functions.abs is df_abs
    assert functions.sin is sin

    msg = "cannot import name 'foobar' from 'datafusion.functions'"
    with pytest.raises(ImportError, match=msg):
        from datafusion.functions import foobar  # noqa: F401


def test_classes_are_inheritable():
    class MyExecContext(SessionContext):
        pass

    class MyExpression(Expr):
        pass

    class MyDataFrame(DataFrame):
        pass
