"""Tests for PolarsAdapter (guarded by polars availability)."""
import pytest

pl = pytest.importorskip("polars")

from kanoniv.adapters.polars import PolarsAdapter
from kanoniv.source import Source


class TestPolarsAdapter:
    def test_schema_type_inference(self):
        df = pl.DataFrame(
            {
                "id": [1, 2, 3],
                "name": ["Alice", "Bob", "Charlie"],
                "score": [9.5, 8.0, 7.2],
                "active": [True, False, True],
            }
        )
        adapter = PolarsAdapter(df)
        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):
        from datetime import date

        df = pl.DataFrame({"created": [date(2024, 1, 1), date(2024, 6, 15)]})
        adapter = PolarsAdapter(df)
        schema = adapter.schema()
        assert schema.columns[0].dtype == "date"

    def test_null_handling(self):
        df = pl.DataFrame(
            {
                "name": ["Alice", None, "Charlie"],
                "score": [1.0, None, 3.0],
            }
        )
        adapter = PolarsAdapter(df)
        rows = list(adapter.iter_rows())
        assert rows[1]["name"] == ""
        assert rows[1]["score"] == ""

    def test_iter_rows_matches_dataframe(self):
        df = pl.DataFrame({"id": [10, 20], "name": ["X", "Y"]})
        adapter = PolarsAdapter(df)
        rows = list(adapter.iter_rows())
        assert len(rows) == 2
        assert rows[0]["id"] == "10"
        assert rows[1]["name"] == "Y"

    def test_row_count(self):
        df = pl.DataFrame({"a": range(50)})
        adapter = PolarsAdapter(df)
        assert adapter.row_count() == 50

    def test_source_from_polars(self):
        df = pl.DataFrame({"id": [1, 2], "email": ["a@b.com", "c@d.com"]})
        src = Source.from_polars("test", df, 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="DataFrame"):
            PolarsAdapter({"not": "a dataframe"})

    def test_nullable_detection(self):
        df = pl.DataFrame(
            {
                "a": [1, 2, 3],
                "b": [1, None, 3],
            }
        )
        adapter = PolarsAdapter(df)
        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_dataframe(self):
        df = pl.DataFrame({"id": [], "name": []}).cast({"id": pl.Int64, "name": pl.Utf8})
        adapter = PolarsAdapter(df)
        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):
        df = pl.DataFrame({"x": ["a", "b", "c", "d", "e", "f"]})
        adapter = PolarsAdapter(df)
        schema = adapter.schema()
        assert len(schema.columns[0].sample_values) == 5
