# 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 uuid
from datetime import date, datetime
from pathlib import Path

import datafusion
import pyarrow as pa
import pytest
from datafusion import SessionContext
from packaging.version import Version
from pyiceberg.catalog import Catalog, load_catalog
from pyiceberg_core.datafusion import IcebergDataFusionTable

if Version(datafusion.__version__) < Version("53.0.0"):
    pytest.skip(
        "Iceberg table provider requires datafusion>=53 for FFI compatibility",
        allow_module_level=True,
    )


@pytest.fixture(scope="session")
def warehouse(tmp_path_factory: pytest.TempPathFactory) -> Path:
    return tmp_path_factory.mktemp("warehouse")


@pytest.fixture(scope="session")
def catalog(warehouse: Path):
    catalog = load_catalog(
        "default",
        uri=f"sqlite:///{warehouse}/pyiceberg_catalog.db",
        warehouse=f"file://{warehouse}",
    )
    yield catalog
    catalog.close()


@pytest.fixture(scope="session")
def arrow_table_with_null() -> "pa.Table":
    """Pyarrow table with all kinds of columns."""
    import pyarrow as pa

    return pa.Table.from_pydict(
        {
            "bool": [False, None, True],
            "string": ["a", None, "z"],
            # Go over the 16 bytes to kick in truncation
            "string_long": ["a" * 22, None, "z" * 22],
            "int": [1, None, 9],
            "long": [1, None, 9],
            "float": [0.0, None, 0.9],
            "double": [0.0, None, 0.9],
            # 'time': [1_000_000, None, 3_000_000],  # Example times: 1s, none, and 3s past midnight #Spark does not support time fields
            "timestamp": [
                datetime(2023, 1, 1, 19, 25, 00),  # noqa: DTZ001
                None,
                datetime(2023, 3, 1, 19, 25, 00),  # noqa: DTZ001
            ],
            # "timestamptz": [
            #     datetime(2023, 1, 1, 19, 25, 00, tzinfo=timezone.utc),
            #     None,
            #     datetime(2023, 3, 1, 19, 25, 00, tzinfo=timezone.utc),
            # ],
            "date": [date(2023, 1, 1), None, date(2023, 3, 1)],
            # Not supported by Spark
            # 'time': [time(1, 22, 0), None, time(19, 25, 0)],
            # Not natively supported by Arrow
            # 'uuid': [uuid.UUID('00000000-0000-0000-0000-000000000000').bytes, None, uuid.UUID('11111111-1111-1111-1111-111111111111').bytes],
            "binary": [b"\01", None, b"\22"],
            "fixed": [
                uuid.UUID("00000000-0000-0000-0000-000000000000").bytes,
                None,
                uuid.UUID("11111111-1111-1111-1111-111111111111").bytes,
            ],
        },
    )


def test_register_iceberg_table_provider(
    catalog: Catalog, arrow_table_with_null: pa.Table
) -> None:
    catalog.create_namespace_if_not_exists("default")
    iceberg_table = catalog.create_table_if_not_exists(
        "default.dataset",
        schema=arrow_table_with_null.schema,
    )
    iceberg_table.append(arrow_table_with_null)

    iceberg_table_provider = IcebergDataFusionTable(
        identifier=iceberg_table.name(),
        metadata_location=iceberg_table.metadata_location,
        file_io_properties=iceberg_table.io.properties,
    )

    ctx = SessionContext()
    ctx.register_table("test", iceberg_table_provider)

    datafusion_table = ctx.table("test")
    assert datafusion_table is not None

    # check that the schema is the same
    from pyiceberg.io.pyarrow import _pyarrow_schema_ensure_small_types

    assert _pyarrow_schema_ensure_small_types(
        datafusion_table.schema()
    ) == _pyarrow_schema_ensure_small_types(iceberg_table.schema().as_arrow())
    # large/small type mismatches, fixed in pyiceberg 0.10.0
    # assert datafusion_table.schema() == iceberg_table.schema().as_arrow()

    # check that the data is the same
    assert (
        datafusion_table.to_arrow_table().to_pylist()
        == iceberg_table.scan().to_arrow().to_pylist()
    )
    # large/small type mismatches, fixed in pyiceberg 0.10.0
    # assert datafusion_table.to_arrow_table() == iceberg_table.scan().to_arrow()


def test_register_pyiceberg_table(
    catalog: Catalog, arrow_table_with_null: pa.Table
) -> None:
    from types import MethodType

    catalog.create_namespace_if_not_exists("default")
    iceberg_table = catalog.create_table_if_not_exists(
        "default.dataset",
        schema=arrow_table_with_null.schema,
    )
    iceberg_table.append(arrow_table_with_null)

    # monkey patch the __datafusion_table_provider__ method to the iceberg table
    def __datafusion_table_provider__(self, session):
        return IcebergDataFusionTable(
            identifier=self.name(),
            metadata_location=self.metadata_location,
            file_io_properties=self.io.properties,
        ).__datafusion_table_provider__(session)

    iceberg_table.__datafusion_table_provider__ = MethodType(
        __datafusion_table_provider__, iceberg_table
    )

    ctx = SessionContext()
    ctx.register_table("test", iceberg_table)

    datafusion_table = ctx.table("test")
    assert datafusion_table is not None
