# #region NativeFilterExtractionTests [TYPE Module] [C:3] [SEMANTICS tests, superset, native, filters, permalink, filter_state]
# @BRIEF Verify native filter extraction from permalinks and native_filters_key URLs.
# @LAYER Domain
# @RELATION BINDS_TO ->[SupersetClient]
# @RELATION BINDS_TO ->[AsyncSupersetClient]
# @RELATION BINDS_TO ->[FilterState]
import json
from unittest.mock import MagicMock

from src.core.config_models import Environment
from src.core.superset_client import SupersetClient
from src.core.utils.superset_context_extractor import (
    SupersetContextExtractor,
    SupersetParsedContext,
    sanitize_imported_filter_for_assistant,
)
from src.models.filter_state import (
    ExtraFormDataMerge,
    FilterState,
    NativeFilterDataMask,
    ParsedNativeFilters,
)


# #region _make_environment [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
def _make_environment() -> Environment:
    return Environment(
        id="env-1",
        name="DEV",
        url="http://superset.local",
        username="demo",
        password="secret",
    )
# #endregion _make_environment
# #region test_extract_native_filters_from_permalink [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Extract native filters from a permalink key.
def test_extract_native_filters_from_permalink():
    client = SupersetClient(_make_environment())
    client.get_dashboard_permalink_state = MagicMock(
        return_value={
            "result": {
                "state": {
                    "dataMask": {
                        "filter_country": {
                            "extraFormData": {
                                "filters": [
                                    {"col": "country", "op": "IN", "val": ["DE", "FR"]}
                                ]
                            },
                            "filterState": {"value": ["DE", "FR"]},
                            "ownState": {},
                        },
                        "filter_date": {
                            "extraFormData": {"time_range": "2020-01-01 : 2024-12-31"},
                            "filterState": {"value": "2020-01-01 : 2024-12-31"},
                            "ownState": {},
                        },
                    },
                    "activeTabs": ["tab1", "tab2"],
                    "anchor": "SECTION1",
                    "chartStates": {"chart_1": {}},
                }
            }
        }
    )
    result = client.extract_native_filters_from_permalink("test-permalink-key")
    assert result["permalink_key"] == "test-permalink-key"
    assert "dataMask" in result
    assert "filter_country" in result["dataMask"]
    assert "filter_date" in result["dataMask"]
    assert result["dataMask"]["filter_country"]["extraFormData"]["filters"][0][
        "val"
    ] == ["DE", "FR"]
    assert result["activeTabs"] == ["tab1", "tab2"]
    assert result["anchor"] == "SECTION1"
# #endregion test_extract_native_filters_from_permalink
# #region test_extract_native_filters_from_permalink_direct_response [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Handle permalink response without result wrapper.
def test_extract_native_filters_from_permalink_direct_response():
    client = SupersetClient(_make_environment())
    client.get_dashboard_permalink_state = MagicMock(
        return_value={
            "state": {
                "dataMask": {
                    "filter_1": {
                        "extraFormData": {"filters": []},
                        "filterState": {},
                        "ownState": {},
                    }
                }
            }
        }
    )
    result = client.extract_native_filters_from_permalink("direct-key")
    assert result["permalink_key"] == "direct-key"
    assert "filter_1" in result["dataMask"]
# #endregion test_extract_native_filters_from_permalink_direct_response
# #region test_extract_native_filters_from_key [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Extract native filters from a native_filters_key.
def test_extract_native_filters_from_key():
    client = SupersetClient(_make_environment())
    client.get_native_filter_state = MagicMock(
        return_value={
            "result": {
                "value": json.dumps(
                    {
                        "filter_region": {
                            "id": "filter_region",
                            "extraFormData": {
                                "filters": [
                                    {"col": "region", "op": "IN", "val": ["EMEA"]}
                                ]
                            },
                            "filterState": {"value": ["EMEA"]},
                        }
                    }
                )
            }
        }
    )
    result = client.extract_native_filters_from_key(123, "filter-state-key")
    assert result["dashboard_id"] == 123
    assert result["filter_state_key"] == "filter-state-key"
    assert "dataMask" in result
    assert "filter_region" in result["dataMask"]
    assert result["dataMask"]["filter_region"]["extraFormData"]["filters"][0][
        "val"
    ] == ["EMEA"]
# #endregion test_extract_native_filters_from_key
# #region test_extract_native_filters_from_key_single_filter [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Handle single filter format in native filter state.
def test_extract_native_filters_from_key_single_filter():
    client = SupersetClient(_make_environment())
    client.get_native_filter_state = MagicMock(
        return_value={
            "result": {
                "value": json.dumps(
                    {
                        "id": "single_filter",
                        "extraFormData": {
                            "filters": [{"col": "status", "op": "==", "val": "active"}]
                        },
                        "filterState": {"value": "active"},
                    }
                )
            }
        }
    )
    result = client.extract_native_filters_from_key(456, "single-key")
    assert "dataMask" in result
    assert "single_filter" in result["dataMask"]
    assert (
        result["dataMask"]["single_filter"]["extraFormData"]["filters"][0]["col"]
        == "status"
    )
# #endregion test_extract_native_filters_from_key_single_filter
# #region test_extract_native_filters_from_key_dict_value [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Handle filter state value as dict instead of JSON string.
def test_extract_native_filters_from_key_dict_value():
    client = SupersetClient(_make_environment())
    client.get_native_filter_state = MagicMock(
        return_value={
            "result": {
                "value": {
                    "filter_id": {
                        "extraFormData": {"filters": []},
                        "filterState": {},
                    }
                }
            }
        }
    )
    result = client.extract_native_filters_from_key(789, "dict-key")
    assert "dataMask" in result
    assert "filter_id" in result["dataMask"]
# #endregion test_extract_native_filters_from_key_dict_value
# #region test_parse_dashboard_url_for_filters_permalink [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Parse permalink URL format.
def test_parse_dashboard_url_for_filters_permalink():
    client = SupersetClient(_make_environment())
    client.extract_native_filters_from_permalink = MagicMock(
        return_value={"dataMask": {"f1": {}}, "permalink_key": "abc123"}
    )
    result = client.parse_dashboard_url_for_filters(
        "http://superset.local/superset/dashboard/p/abc123/"
    )
    assert result["filter_type"] == "permalink"
    assert result["filters"]["dataMask"]["f1"] == {}
# #endregion test_parse_dashboard_url_for_filters_permalink
# #region test_parse_dashboard_url_for_filters_native_key [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Parse native_filters_key URL format with numeric dashboard ID.
def test_parse_dashboard_url_for_filters_native_key():
    client = SupersetClient(_make_environment())
    client.extract_native_filters_from_key = MagicMock(
        return_value={
            "dataMask": {"f2": {}},
            "dashboard_id": 42,
            "filter_state_key": "xyz",
        }
    )
    result = client.parse_dashboard_url_for_filters(
        "http://superset.local/dashboard/42/?native_filters_key=xyz"
    )
    assert result["filter_type"] == "native_filters_key"
    assert result["dashboard_id"] == 42
    assert result["filters"]["dataMask"]["f2"] == {}
# #endregion test_parse_dashboard_url_for_filters_native_key
# #region test_parse_dashboard_url_for_filters_native_key_slug [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Parse native_filters_key URL format when dashboard reference is a slug, not a numeric ID.
def test_parse_dashboard_url_for_filters_native_key_slug():
    client = SupersetClient(_make_environment())
    # Simulate slug resolution: get_dashboard returns the dashboard with numeric ID
    client.get_dashboard = MagicMock(
        return_value={
            "result": {"id": 99, "dashboard_title": "COVID Dashboard", "slug": "covid"}
        }
    )
    client.extract_native_filters_from_key = MagicMock(
        return_value={
            "dataMask": {"f_slug": {}},
            "dashboard_id": 99,
            "filter_state_key": "abc123",
        }
    )
    result = client.parse_dashboard_url_for_filters(
        "http://superset.local/superset/dashboard/covid/?native_filters_key=abc123"
    )
    assert result["filter_type"] == "native_filters_key"
    assert result["dashboard_id"] == 99
    assert result["filters"]["dataMask"]["f_slug"] == {}
    client.get_dashboard.assert_called_once_with("covid")
    client.extract_native_filters_from_key.assert_called_once_with(99, "abc123")
# #endregion test_parse_dashboard_url_for_filters_native_key_slug
# #region test_parse_dashboard_url_for_filters_native_key_slug_resolution_fails [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Gracefully handle slug resolution failure for native_filters_key URL.
def test_parse_dashboard_url_for_filters_native_key_slug_resolution_fails():
    client = SupersetClient(_make_environment())
    client.get_dashboard = MagicMock(side_effect=Exception("Not found"))
    result = client.parse_dashboard_url_for_filters(
        "http://superset.local/dashboard/unknownslug/?native_filters_key=key1"
    )
    assert result["filter_type"] is None
    assert result["dashboard_id"] is None
# #endregion test_parse_dashboard_url_for_filters_native_key_slug_resolution_fails
# #region test_parse_dashboard_url_for_filters_native_filters_direct [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Parse native_filters direct query param.
def test_parse_dashboard_url_for_filters_native_filters_direct():
    client = SupersetClient(_make_environment())
    result = client.parse_dashboard_url_for_filters(
        "http://superset.local/dashboard/1/?native_filters="
        + json.dumps({"filter_1": {"col": "x", "op": "==", "val": "y"}})
    )
    assert result["filter_type"] == "native_filters"
    assert "dataMask" in result["filters"]
# #endregion test_parse_dashboard_url_for_filters_native_filters_direct
# #region test_parse_dashboard_url_for_filters_no_filters [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Return empty result when no filters present.
def test_parse_dashboard_url_for_filters_no_filters():
    client = SupersetClient(_make_environment())
    result = client.parse_dashboard_url_for_filters(
        "http://superset.local/dashboard/1/"
    )
    assert result["filter_type"] is None
    assert result["filters"] == {}
# #endregion test_parse_dashboard_url_for_filters_no_filters
# #region test_extra_form_data_merge [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Test ExtraFormDataMerge correctly merges dictionaries.
def test_extra_form_data_merge():
    merger = ExtraFormDataMerge()
    original = {
        "filters": [{"col": "a", "op": "IN", "val": [1, 2]}],
        "time_range": "2020-01-01 : 2021-01-01",
        "extras": {"where": "x > 0"},
    }
    new = {
        "filters": [{"col": "b", "op": "==", "val": "test"}],
        "time_range": "2022-01-01 : 2023-01-01",
        "columns": ["col1", "col2"],
    }
    result = merger.merge(original, new)
    # Filters should be appended
    assert len(result["filters"]) == 2
    assert result["filters"][0]["col"] == "a"
    assert result["filters"][1]["col"] == "b"
    # Time range should be overridden
    assert result["time_range"] == "2022-01-01 : 2023-01-01"
    # Extras should remain
    assert result["extras"] == {"where": "x > 0"}
    # New columns should be added
    assert result["columns"] == ["col1", "col2"]
# #endregion test_extra_form_data_merge
# #region test_filter_state_model [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Test FilterState Pydantic model.
def test_filter_state_model():
    state = FilterState(
        extraFormData={"filters": [{"col": "x", "op": "==", "val": "y"}]},
        filterState={"value": "y"},
        ownState={"selectedValues": ["y"]},
    )
    assert state.extraFormData["filters"][0]["col"] == "x"
    assert state.filterState["value"] == "y"
    assert state.ownState["selectedValues"] == ["y"]
# #endregion test_filter_state_model
# #region test_parsed_native_filters_model [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Test ParsedNativeFilters Pydantic model.
def test_parsed_native_filters_model():
    filters = ParsedNativeFilters(
        dataMask={"f1": {"extraFormData": {}, "filterState": {}}},
        filter_type="permalink",
        dashboard_id="42",
        permalink_key="abc",
    )
    assert filters.has_filters() is True
    assert filters.get_filter_count() == 1
    assert filters.filter_type == "permalink"
# #endregion test_parsed_native_filters_model
# #region test_parsed_native_filters_empty [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Test ParsedNativeFilters with no filters.
def test_parsed_native_filters_empty():
    filters = ParsedNativeFilters()
    assert filters.has_filters() is False
    assert filters.get_filter_count() == 0
# #endregion test_parsed_native_filters_empty
# #region test_native_filter_data_mask_model [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Test NativeFilterDataMask model.
def test_native_filter_data_mask_model():
    data_mask = NativeFilterDataMask(
        filters={
            "filter_1": FilterState(extraFormData={"filters": []}, filterState={}),
            "filter_2": FilterState(
                extraFormData={"time_range": "..."}, filterState={}
            ),
        }
    )
    assert data_mask.get_filter_ids() == ["filter_1", "filter_2"]
    assert data_mask.get_extra_form_data("filter_1") == {"filters": []}
    assert data_mask.get_extra_form_data("nonexistent") == {}
# #endregion test_native_filter_data_mask_model
# #region test_recover_imported_filters_reconciles_raw_native_filter_ids_to_metadata_names [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Reconcile raw native filter ids from state to canonical metadata filter names.
def test_recover_imported_filters_reconciles_raw_native_filter_ids_to_metadata_names():
    client = MagicMock()
    client.get_dashboard.return_value = {
        "result": {
            "json_metadata": json.dumps(
                {
                    "native_filter_configuration": [
                        {
                            "id": "NATIVE_FILTER-EWNH3M70z",
                            "name": "Country",
                            "label": "Country",
                        }
                    ]
                }
            )
        }
    }
    extractor = SupersetContextExtractor(_make_environment(), client=client)
    parsed_context = SupersetParsedContext(
        source_url="http://superset.local/dashboard/42/?native_filters_key=abc",
        dataset_ref="dataset:42",
        dashboard_id=42,
        imported_filters=[
            {
                "filter_name": "NATIVE_FILTER-EWNH3M70z",
                "display_name": "NATIVE_FILTER-EWNH3M70z",
                "raw_value": ["DE", "FR"],
                "normalized_value": {
                    "filter_clauses": [
                        {"col": "country", "op": "IN", "val": ["DE", "FR"]}
                    ],
                    "extra_form_data": {
                        "filters": [{"col": "country", "op": "IN", "val": ["DE", "FR"]}]
                    },
                    "value_origin": "filter_state",
                },
                "source": "superset_native_filters_key",
                "recovery_status": "recovered",
                "requires_confirmation": False,
                "notes": "Recovered from Superset native_filters_key state",
            }
        ],
    )
    result = extractor.recover_imported_filters(parsed_context)
    assert len(result) == 1
    assert result[0]["filter_name"] == "Country"
    assert result[0]["display_name"] == "Country"
    assert result[0]["raw_value"] == ["DE", "FR"]
    assert result[0]["source"] == "superset_native_filters_key"
    assert result[0]["normalized_value"] == {
        "filter_clauses": [{"col": "country", "op": "IN", "val": ["DE", "FR"]}],
        "extra_form_data": {
            "filters": [{"col": "country", "op": "IN", "val": ["DE", "FR"]}]
        },
        "value_origin": "filter_state",
    }
# #endregion test_recover_imported_filters_reconciles_raw_native_filter_ids_to_metadata_names
# #region test_recover_imported_filters_collapses_state_and_metadata_duplicates_into_one_canonical_filter [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Collapse raw-id state entries and metadata entries into one canonical filter.
def test_recover_imported_filters_collapses_state_and_metadata_duplicates_into_one_canonical_filter():
    client = MagicMock()
    client.get_dashboard.return_value = {
        "result": {
            "json_metadata": json.dumps(
                {
                    "native_filter_configuration": [
                        {
                            "id": "NATIVE_FILTER-EWNH3M70z",
                            "name": "Country",
                            "label": "Country",
                        },
                        {
                            "id": "NATIVE_FILTER-vv123",
                            "name": "Region",
                            "label": "Region",
                        },
                    ]
                }
            )
        }
    }
    extractor = SupersetContextExtractor(_make_environment(), client=client)
    parsed_context = SupersetParsedContext(
        source_url="http://superset.local/dashboard/42/?native_filters_key=abc",
        dataset_ref="dataset:42",
        dashboard_id=42,
        imported_filters=[
            {
                "filter_name": "NATIVE_FILTER-EWNH3M70z",
                "display_name": "Country",
                "raw_value": ["DE", "FR"],
                "source": "superset_native_filters_key",
                "recovery_status": "recovered",
                "requires_confirmation": False,
                "notes": "Recovered from Superset native_filters_key state",
            }
        ],
    )
    result = extractor.recover_imported_filters(parsed_context)
    assert len(result) == 2
    country_filter = next(item for item in result if item["filter_name"] == "Country")
    region_filter = next(item for item in result if item["filter_name"] == "Region")
    assert country_filter["raw_value"] == ["DE", "FR"]
    assert country_filter["recovery_status"] == "recovered"
    assert region_filter["raw_value"] is None
    assert region_filter["recovery_status"] == "partial"
# #endregion test_recover_imported_filters_collapses_state_and_metadata_duplicates_into_one_canonical_filter
# #region test_recover_imported_filters_preserves_unmatched_raw_native_filter_ids [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Preserve unmatched raw native filter ids as fallback diagnostics when metadata mapping is unavailable.
def test_recover_imported_filters_preserves_unmatched_raw_native_filter_ids():
    client = MagicMock()
    client.get_dashboard.return_value = {
        "result": {
            "json_metadata": json.dumps(
                {
                    "native_filter_configuration": [
                        {
                            "id": "NATIVE_FILTER-EWNH3M70z",
                            "name": "Country",
                            "label": "Country",
                        }
                    ]
                }
            )
        }
    }
    extractor = SupersetContextExtractor(_make_environment(), client=client)
    parsed_context = SupersetParsedContext(
        source_url="http://superset.local/dashboard/42/?native_filters_key=abc",
        dataset_ref="dataset:42",
        dashboard_id=42,
        imported_filters=[
            {
                "filter_name": "UNKNOWN_NATIVE_FILTER",
                "display_name": "UNKNOWN_NATIVE_FILTER",
                "raw_value": ["orphan"],
                "source": "superset_native_filters_key",
                "recovery_status": "recovered",
                "requires_confirmation": False,
                "notes": "Recovered from Superset native_filters_key state",
            }
        ],
    )
    result = extractor.recover_imported_filters(parsed_context)
    assert len(result) == 2
    assert any(
        item["filter_name"] == "Country" and item["recovery_status"] == "partial"
        for item in result
    )
    assert any(
        item["filter_name"] == "UNKNOWN_NATIVE_FILTER"
        and item["raw_value"] == ["orphan"]
        and item["source"] == "superset_native_filters_key"
        for item in result
    )
# #endregion test_recover_imported_filters_preserves_unmatched_raw_native_filter_ids
# #region test_extract_imported_filters_preserves_clause_level_native_filter_payload_for_preview [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Recovered native filter state should preserve exact Superset clause payload and time extras for preview compilation.
def test_extract_imported_filters_preserves_clause_level_native_filter_payload_for_preview():
    extractor = SupersetContextExtractor(_make_environment(), client=MagicMock())
    imported_filters = extractor._extract_imported_filters(
        {
            "native_filter_state": {
                "NATIVE_FILTER-1": {
                    "id": "NATIVE_FILTER-1",
                    "filterState": {"label": "Country", "value": ["DE"]},
                    "extraFormData": {
                        "filters": [{"col": "country_code", "op": "IN", "val": ["DE"]}],
                        "time_range": "Last month",
                    },
                }
            }
        }
    )
    assert imported_filters == [
        {
            "filter_name": "NATIVE_FILTER-1",
            "raw_value": ["DE"],
            "display_name": "Country",
            "normalized_value": {
                "filter_clauses": [{"col": "country_code", "op": "IN", "val": ["DE"]}],
                "extra_form_data": {
                    "filters": [{"col": "country_code", "op": "IN", "val": ["DE"]}],
                    "time_range": "Last month",
                },
                "value_origin": "filter_state",
            },
            "source": "superset_native_filters_key",
            "recovery_status": "recovered",
            "requires_confirmation": False,
            "notes": "Recovered from Superset native_filters_key state",
        }
    ]
# #endregion test_extract_imported_filters_preserves_clause_level_native_filter_payload_for_preview
# #region test_sanitize_imported_filter_for_assistant_masks_sensitive_raw_values [TYPE Function]
# @RELATION BINDS_TO -> NativeFilterExtractionTests
# @BRIEF Assistant-facing imported-filter payload should redact likely PII while preserving structure metadata.
def test_sanitize_imported_filter_for_assistant_masks_sensitive_raw_values():
    result = sanitize_imported_filter_for_assistant(
        {
            "filter_name": "customer_email",
            "raw_value": ["alice@example.com", "1234567890"],
            "normalized_value": {"filter_clauses": []},
            "source": "manual",
        }
    )
    assert result["raw_value"] == ["***@example.com", "********90"]
    assert result["raw_value_masked"] is True
    assert result["normalized_value"] == {"filter_clauses": []}
# #endregion test_sanitize_imported_filter_for_assistant_masks_sensitive_raw_values
# #endregion NativeFilterExtractionTests
