"""Tests for statistical data profiler."""

from __future__ import annotations

from orxaq.fabric.profiler import DataProfiler


class TestDataProfiler:
    def setup_method(self):
        self.profiler = DataProfiler()

    def test_row_and_column_counts(self):
        data = [{"a": 1, "b": 2}, {"a": 3, "b": 4}]
        profile = self.profiler.profile(data)
        assert profile.row_count == 2
        assert profile.column_count == 2

    def test_numeric_stats(self):
        data = [{"x": 10.0}, {"x": 20.0}, {"x": 30.0}]
        profile = self.profiler.profile(data)
        col = profile.columns["x"]
        assert col.min_val == 10.0
        assert col.max_val == 30.0
        assert col.mean == 20.0
        assert col.median == 20.0

    def test_null_counts(self):
        data = [{"x": 1}, {"x": None}, {"x": None}]
        profile = self.profiler.profile(data)
        col = profile.columns["x"]
        assert col.null_count == 2
        assert abs(col.null_pct - 2 / 3) < 0.01

    def test_unique_count(self):
        data = [{"x": "a"}, {"x": "b"}, {"x": "a"}]
        profile = self.profiler.profile(data)
        assert profile.columns["x"].unique_count == 2

    def test_string_stats(self):
        data = [{"name": "Al"}, {"name": "Bob"}, {"name": "Charlie"}, {"name": "Al"}]
        profile = self.profiler.profile(data)
        col = profile.columns["name"]
        assert col.dtype == "str"
        assert col.min_length == 2
        assert col.max_length == 7
        assert col.top_values[0] == ("Al", 2)  # Most common

    def test_empty_data(self):
        profile = self.profiler.profile([])
        assert profile.row_count == 0
        assert profile.column_count == 0

    def test_mixed_types_inferred_as_float(self):
        data = [{"x": 1}, {"x": 2.5}]
        profile = self.profiler.profile(data)
        assert profile.columns["x"].dtype == "float"

    def test_all_null_column(self):
        data = [{"x": None}, {"x": None}]
        profile = self.profiler.profile(data)
        col = profile.columns["x"]
        assert col.null_count == 2
        assert col.dtype == "unknown"

    def test_percentiles(self):
        data = [{"v": float(i)} for i in range(100)]
        profile = self.profiler.profile(data)
        col = profile.columns["v"]
        assert col.p25 is not None
        assert col.p75 is not None
        assert col.p25 < col.p75

    def test_bool_dtype(self):
        """Cover line 54: bool type detected in _infer_dtype."""
        data = [{"flag": True}, {"flag": False}, {"flag": True}]
        profile = self.profiler.profile(data)
        assert profile.columns["flag"].dtype == "bool"

    def test_other_dtype(self):
        """Cover line 62: non-standard types fallback to 'other'."""
        data = [{"x": [1, 2]}, {"x": {3: 4}}]
        profile = self.profiler.profile(data)
        assert profile.columns["x"].dtype == "other"

    def test_none_values_skipped(self):
        """Cover line 52: None values are skipped in dtype inference."""
        from orxaq.fabric.profiler import _infer_dtype

        assert _infer_dtype([None, None]) == "unknown"
        assert _infer_dtype([None, 1, None]) == "int"
