# #region Test.Superset.Charts [C:3] [TYPE Module] [SEMANTICS test,superset,charts]
# @BRIEF Tests for core/superset_client/_charts.py — SupersetChartsMixin.
# @RELATION BINDS_TO -> [SupersetChartsMixin]
# @TEST_EDGE: extract_chart_ids_non_dict_walks -> empty set
# @TEST_EDGE: extract_chart_ids_chart_n_pattern -> CHART-123 format

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))

from unittest.mock import AsyncMock, MagicMock, patch
import pytest


class TestGetChart:
    """Verify get_chart method."""

    @pytest.fixture
    def mixin(self):
        from src.core.superset_client._charts import SupersetChartsMixin

        m = SupersetChartsMixin()
        m.client = MagicMock()
        m.client.request = AsyncMock(return_value={"id": 42, "slice_name": "Test"})
        return m

    async def test_get_chart_returns_dict(self, mixin):
        result = await mixin.get_chart(42)
        assert result["id"] == 42
        assert result["slice_name"] == "Test"
        mixin.client.request.assert_called_once_with(method="GET", endpoint="/chart/42")


class TestGetCharts:
    """Verify get_charts method."""

    @pytest.fixture
    def mixin(self):
        from src.core.superset_client._charts import SupersetChartsMixin

        m = SupersetChartsMixin()
        m.client = MagicMock()
        m._validate_query_params = MagicMock(side_effect=lambda q: q or {})
        m._fetch_all_pages = AsyncMock(
            return_value=[{"id": 1, "slice_name": "Chart 1"}, {"id": 2, "slice_name": "Chart 2"}]
        )
        return m

    async def test_get_charts_returns_count_and_list(self, mixin):
        total, charts = await mixin.get_charts()
        assert total == 2
        assert len(charts) == 2
        mixin._fetch_all_pages.assert_called_once()

    async def test_get_charts_with_query_params(self, mixin):
        total, charts = await mixin.get_charts(query={"page": 0, "page_size": 50})
        assert total == 2

    async def test_get_charts_adds_default_columns(self, mixin):
        mixin._validate_query_params = MagicMock(return_value={})
        total, charts = await mixin.get_charts()
        mixin._fetch_all_pages.assert_called_once_with(
            endpoint="/chart/",
            pagination_options={
                "base_query": {"columns": ["id", "uuid", "slice_name", "viz_type"]},
                "results_field": "result",
            },
        )


class TestExtractChartIdsFromLayout:
    """Verify _extract_chart_ids_from_layout."""

    @pytest.fixture
    def mixin(self):
        from src.core.superset_client._charts import SupersetChartsMixin

        return SupersetChartsMixin()

    def test_extracts_chart_id_key(self, mixin):
        payload = {"chartId": 42}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {42}

    def test_extracts_chart_id_key_variant(self, mixin):
        payload = {"chart_id": 99}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {99}

    def test_extracts_slice_id(self, mixin):
        payload = {"slice_id": 77}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {77}

    def test_extracts_sliceId(self, mixin):
        payload = {"sliceId": 55}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {55}

    def test_extracts_chart_n_pattern(self, mixin):
        payload = {"id": "CHART-123"}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {123}

    def test_ignores_non_matching_string_id(self, mixin):
        payload = {"id": "some-other-id"}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == set()

    def test_handles_nested_dicts(self, mixin):
        payload = {"children": {"child": {"chartId": 10}}, "other": {"slice_id": 20}}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {10, 20}

    def test_handles_lists(self, mixin):
        payload = {"rows": [{"chartId": 1}, {"chartId": 2}]}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == {1, 2}

    def test_empty_payload(self, mixin):
        result = mixin._extract_chart_ids_from_layout({})
        assert result == set()

    def test_non_dict_payload(self, mixin):
        result = mixin._extract_chart_ids_from_layout("string")
        assert result == set()

    def test_none_payload(self, mixin):
        result = mixin._extract_chart_ids_from_layout(None)
        assert result == set()

    def test_non_parseable_chart_n(self, mixin):
        payload = {"id": "CHART-abc"}  # non-numeric
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == set()

    def test_non_parseable_chart_id_value(self, mixin):
        payload = {"chartId": "not-a-number"}
        result = mixin._extract_chart_ids_from_layout(payload)
        assert result == set()

    def test_int_conversion_error_in_chart_n(self, mixin):
        """Cover lines 68-69: int() on CHART-N digits fails (defensive)."""
        from unittest.mock import patch

        with patch("src.core.superset_client._charts.int", side_effect=ValueError("mock fail")):
            result = mixin._extract_chart_ids_from_layout({"id": "CHART-123"})
        assert result == set()
# #endregion Test.Superset.Charts
