"""Tests for ArrowAdapter (guarded by pyarrow availability)."""
import pytest

pa = pytest.importorskip("pyarrow")

from kanoniv.adapters.arrow import ArrowAdapter
from kanoniv.source import Source


class TestArrowAdapter:
    def test_schema_type_inference(self):
        table = pa.table(
            {
                "id": pa.array([1, 2, 3], type=pa.int64()),
                "name": pa.array(["Alice", "Bob", "Charlie"], type=pa.string()),
                "score": pa.array([9.5, 8.0, 7.2], type=pa.float64()),
                "active": pa.array([True, False, True], type=pa.bool_()),
            }
        )
        adapter = ArrowAdapter(table)
        schema = adapter.schema()
        col_map = {c.name: c for c in schema.columns}
        assert col_map["id"].dtype == "number"
        assert col_map["name"].dtype == "string"
        assert col_map["score"].dtype == "number"
        assert col_map["active"].dtype == "boolean"

    def test_schema_date_inference(self):
        import datetime

        table = pa.table(
            {
                "created": pa.array(
                    [datetime.date(2024, 1, 1), datetime.date(2024, 6, 15)],
                    type=pa.date32(),
                ),
            }
        )
        adapter = ArrowAdapter(table)
        schema = adapter.schema()
        assert schema.columns[0].dtype == "date"

    def test_null_handling(self):
        table = pa.table(
            {
                "name": pa.array(["Alice", None, "Charlie"], type=pa.string()),
                "score": pa.array([1.0, None, 3.0], type=pa.float64()),
            }
        )
        adapter = ArrowAdapter(table)
        rows = list(adapter.iter_rows())
        assert rows[1]["name"] == ""
        assert rows[1]["score"] == ""

    def test_iter_rows_matches_table(self):
        table = pa.table({"id": [10, 20], "name": ["X", "Y"]})
        adapter = ArrowAdapter(table)
        rows = list(adapter.iter_rows())
        assert len(rows) == 2
        assert rows[0]["id"] == "10"
        assert rows[1]["name"] == "Y"

    def test_row_count(self):
        table = pa.table({"a": list(range(50))})
        adapter = ArrowAdapter(table)
        assert adapter.row_count() == 50

    def test_source_from_arrow(self):
        table = pa.table({"id": [1, 2], "email": ["a@b.com", "c@d.com"]})
        src = Source.from_arrow("test", table, primary_key="id")
        entities = src.to_entities("customer")
        assert len(entities) == 2
        assert entities[0]["data"]["email"] == "a@b.com"

    def test_invalid_input_raises(self):
        with pytest.raises(TypeError, match="Table"):
            ArrowAdapter({"not": "a table"})

    def test_nullable_detection(self):
        table = pa.table(
            {
                "a": pa.array([1, 2, 3], type=pa.int64()),
                "b": pa.array([1, None, 3], type=pa.int64()),
            }
        )
        adapter = ArrowAdapter(table)
        schema = adapter.schema()
        col_map = {c.name: c for c in schema.columns}
        assert col_map["a"].nullable is False
        assert col_map["b"].nullable is True

    def test_empty_table(self):
        table = pa.table({"id": pa.array([], type=pa.int64()), "name": pa.array([], type=pa.string())})
        adapter = ArrowAdapter(table)
        assert adapter.row_count() == 0
        assert list(adapter.iter_rows()) == []
        schema = adapter.schema()
        assert len(schema.columns) == 2

    def test_sample_values_in_schema(self):
        table = pa.table({"x": ["a", "b", "c", "d", "e", "f"]})
        adapter = ArrowAdapter(table)
        schema = adapter.schema()
        assert len(schema.columns[0].sample_values) == 5

    def test_timestamp_inference(self):
        import datetime

        table = pa.table(
            {
                "ts": pa.array(
                    [datetime.datetime(2024, 1, 1, 12, 0), datetime.datetime(2024, 6, 15, 8, 30)],
                    type=pa.timestamp("us"),
                ),
            }
        )
        adapter = ArrowAdapter(table)
        schema = adapter.schema()
        assert schema.columns[0].dtype == "date"
