# 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.

from __future__ import annotations

import pyarrow as pa
import pyarrow.dataset as ds
import pytest
from datafusion import SessionContext, Table
from datafusion.catalog import Schema
from datafusion_ffi_example import FixedSchemaProvider, MyCatalogProvider


def create_test_dataset() -> Table:
    """Create a simple test dataset."""
    batch = pa.RecordBatch.from_arrays(
        [pa.array([100, 200, 300]), pa.array([1.1, 2.2, 3.3])],
        names=["id", "value"],
    )
    dataset = ds.dataset([batch])
    return Table(dataset)


@pytest.mark.parametrize("inner_capsule", [True, False])
def test_schema_provider_extract_values(inner_capsule: bool) -> None:
    ctx = SessionContext()

    my_schema_name = "my_schema"

    schema_provider = FixedSchemaProvider()
    if inner_capsule:
        schema_provider = schema_provider.__datafusion_schema_provider__(ctx)

    ctx.catalog().register_schema(my_schema_name, schema_provider)

    expected_schema_name = "my_schema"
    expected_table_name = "my_table"
    expected_table_columns = ["units", "price"]

    default_catalog = ctx.catalog()

    catalog_schemas = default_catalog.names()
    assert expected_schema_name in catalog_schemas
    my_schema = default_catalog.schema(expected_schema_name)
    assert expected_table_name in my_schema.names()
    my_table = my_schema.table(expected_table_name)
    assert expected_table_columns == my_table.schema.names

    result = ctx.table(f"{expected_schema_name}.{expected_table_name}").collect()
    assert len(result) == 2

    # Multi-partition collect order is non-deterministic; sort batches by
    # first value of col0 so col0 and col1 stay aligned.
    result = sorted(result, key=lambda r: r.column(0)[0].as_py())
    col0_result = [r.column(0) for r in result]
    col1_result = [r.column(1) for r in result]
    expected_col0 = [
        pa.array([5, 7], type=pa.int32()),
        pa.array([10, 20, 30], type=pa.int32()),
    ]
    expected_col1 = [
        pa.array([1.5, 2.5], type=pa.float64()),
        pa.array([1, 2, 5], type=pa.float64()),
    ]
    assert col0_result == expected_col0
    assert col1_result == expected_col1


def test_ffi_schema_provider_basic():
    """Test basic FFI SchemaProvider functionality."""
    ctx = SessionContext()

    # Register FFI schema
    schema_provider = FixedSchemaProvider()
    ctx.catalog().register_schema("ffi_schema", schema_provider)

    # Verify the schema exists
    schema = ctx.catalog().schema("ffi_schema")
    table_names = schema.names()
    assert "my_table" in table_names

    # Query the pre-populated table
    result = ctx.sql("SELECT * FROM ffi_schema.my_table").collect()
    assert len(result) == 2
    assert result[0].num_columns == 2


def test_ffi_schema_provider_register_table():
    """Test registering additional tables to FFI SchemaProvider."""
    ctx = SessionContext()

    schema_provider = FixedSchemaProvider()
    ctx.catalog().register_schema("ffi_schema", schema_provider)

    schema = ctx.catalog().schema("ffi_schema")

    # Register a new table
    schema.register_table("additional_table", create_test_dataset())

    # Verify the table was registered
    assert "additional_table" in schema.names()

    # Query the new table
    result = ctx.sql("SELECT * FROM ffi_schema.additional_table").collect()
    assert len(result) == 1
    assert result[0].column(0) == pa.array([100, 200, 300])
    assert result[0].column(1) == pa.array([1.1, 2.2, 3.3])


def test_ffi_schema_provider_deregister_table():
    """Test deregistering tables from FFI SchemaProvider."""
    ctx = SessionContext()

    schema_provider = FixedSchemaProvider()
    ctx.catalog().register_schema("ffi_schema", schema_provider)

    schema = ctx.catalog().schema("ffi_schema")

    # Register two tables
    schema.register_table("temp_table1", create_test_dataset())
    schema.register_table("temp_table2", create_test_dataset())

    # Verify both exist
    names = schema.names()
    assert "temp_table1" in names
    assert "temp_table2" in names

    # Deregister one table
    schema.deregister_table("temp_table1")

    # Verify it's gone
    names = schema.names()
    assert "temp_table1" not in names
    assert "temp_table2" in names


def test_mixed_ffi_and_python_providers():
    """Test mixing FFI and Python providers in the same catalog/schema."""
    ctx = SessionContext()

    # Register FFI catalog
    ffi_catalog = MyCatalogProvider()
    ctx.register_catalog_provider("ffi_catalog", ffi_catalog)

    # Register Python memory schema to FFI catalog
    python_schema = Schema.memory_schema()
    ctx.catalog("ffi_catalog").register_schema("python_schema", python_schema)

    # Add table to Python schema
    python_schema.register_table("python_table", create_test_dataset())

    # Query both FFI table and Python table
    result_ffi = ctx.sql("SELECT * FROM ffi_catalog.my_schema.my_table").collect()
    assert len(result_ffi) == 2

    result_python = ctx.sql(
        "SELECT * FROM ffi_catalog.python_schema.python_table"
    ).collect()
    assert len(result_python) == 1
    assert result_python[0].column(0) == pa.array([100, 200, 300])


def test_ffi_catalog_with_multiple_schemas():
    """Test FFI catalog with multiple schemas of different types."""
    ctx = SessionContext()

    catalog_provider = MyCatalogProvider()
    ctx.register_catalog_provider("multi_catalog", catalog_provider)

    catalog = ctx.catalog("multi_catalog")

    # Register different types of schemas
    ffi_schema = FixedSchemaProvider()
    memory_schema = Schema.memory_schema()

    catalog.register_schema("ffi_schema", ffi_schema)
    catalog.register_schema("memory_schema", memory_schema)

    # Add tables to memory schema
    memory_schema.register_table("mem_table", create_test_dataset())

    # Verify all schemas exist
    names = catalog.names()
    assert "my_schema" in names  # Pre-populated
    assert "ffi_schema" in names
    assert "memory_schema" in names

    # Query tables from each schema
    result = ctx.sql("SELECT * FROM multi_catalog.my_schema.my_table").collect()
    assert len(result) == 2

    result = ctx.sql("SELECT * FROM multi_catalog.ffi_schema.my_table").collect()
    assert len(result) == 2

    result = ctx.sql("SELECT * FROM multi_catalog.memory_schema.mem_table").collect()
    assert len(result) == 1
    assert result[0].column(0) == pa.array([100, 200, 300])


def test_ffi_schema_table_exist():
    """Test table_exist method on FFI SchemaProvider."""
    ctx = SessionContext()

    schema_provider = FixedSchemaProvider()
    ctx.catalog().register_schema("ffi_schema", schema_provider)

    schema = ctx.catalog().schema("ffi_schema")

    # Check pre-populated table
    assert schema.table_exist("my_table")

    # Check non-existent table
    assert not schema.table_exist("nonexistent_table")

    # Register a new table and check
    schema.register_table("new_table", create_test_dataset())
    assert schema.table_exist("new_table")

    # Deregister and check
    schema.deregister_table("new_table")
    assert not schema.table_exist("new_table")
