# #region SupersetContextParsingMixin [C:4] [TYPE Module] [SEMANTICS superset, transform, dashboard, dataset, session, review]
# @LAYER Infrastructure
# @BRIEF Parse supported Superset URLs and recover canonical dataset/dashboard references for review-session intake.
# @RELATION CALLS -> [SupersetClient]
# @RELATION CALLS -> [SupersetContextExtractorBase]
# #endregion SupersetContextParsingMixin
# #region _parsing_imports [TYPE Block]
from __future__ import annotations

from typing import Any, cast
from urllib.parse import parse_qs, urlparse

from ...logger import belief_scope, logger
from ._base import SupersetParsedContext

logger = cast(Any, logger)
# #endregion _parsing_imports
# #region SupersetContextParsingMixin [C:4] [TYPE Class]
# @BRIEF Mixin providing Superset URL parsing logic for the composed SupersetContextExtractor.
class SupersetContextParsingMixin:
    # #region SupersetContextParsingMixin.parse_superset_link [TYPE Function] [C:4]
    # @PURPOSE: Extract candidate identifiers and query state from supported Superset URLs.
    # @RELATION CALLS -> [EXT:method:SupersetClient.get_dashboard_detail]
    # @PRE  link is a non-empty Superset URL compatible with the configured environment.
    # @POST  returns resolved dataset/dashboard context, preserving explicit partial-recovery state if some identifiers cannot be confirmed.
    # @SIDE_EFFECT  may issue Superset API reads to resolve dataset references from dashboard or chart URLs.
    # @DATA_CONTRACT  Input[link:str] -> Output[SupersetParsedContext]
    def parse_superset_link(self, link: str) -> SupersetParsedContext:
        with belief_scope("SupersetContextExtractor.parse_superset_link"):
            normalized_link = str(link or "").strip()
            if not normalized_link:
                logger.explore("Rejected empty Superset link during intake")
                raise ValueError("Superset link must be non-empty")
            parsed_url = urlparse(normalized_link)
            if parsed_url.scheme not in {"http", "https"} or not parsed_url.netloc:
                logger.explore(
                    "Superset link is not a parseable absolute URL",
                    extra={"link": normalized_link},
                )
                raise ValueError("Superset link must be an absolute http(s) URL")
            logger.reason(
                "Parsing Superset link for dataset review intake",
                extra={"path": parsed_url.path, "query": parsed_url.query},
            )
            path_parts = [part for part in parsed_url.path.split("/") if part]
            query_params = parse_qs(parsed_url.query, keep_blank_values=True)
            query_state = self._decode_query_state(query_params)
            dataset_id = self._extract_numeric_identifier(path_parts, "dataset")
            dashboard_id = self._extract_numeric_identifier(path_parts, "dashboard")
            dashboard_ref = self._extract_dashboard_reference(path_parts)
            dashboard_permalink_key = self._extract_dashboard_permalink_key(path_parts)
            chart_id = self._extract_numeric_identifier(path_parts, "chart")
            resource_type = "unknown"
            dataset_ref: str | None = None
            partial_recovery = False
            unresolved_references: list[str] = []
            if dataset_id is not None:
                resource_type = "dataset"
                dataset_ref = f"dataset:{dataset_id}"
                logger.reason(
                    "Resolved direct dataset link",
                    extra={"dataset_id": dataset_id},
                )
            elif dashboard_permalink_key is not None:
                resource_type = "dashboard"
                partial_recovery = True
                dataset_ref = f"dashboard_permalink:{dashboard_permalink_key}"
                unresolved_references.append(
                    "dashboard_permalink_dataset_binding_unresolved"
                )
                logger.reason(
                    "Resolving dashboard permalink state from Superset",
                    extra={"permalink_key": dashboard_permalink_key},
                )
                permalink_payload = self.client.get_dashboard_permalink_state(
                    dashboard_permalink_key
                )
                permalink_state = (
                    permalink_payload.get("state", permalink_payload)
                    if isinstance(permalink_payload, dict)
                    else {}
                )
                if isinstance(permalink_state, dict):
                    for key, value in permalink_state.items():
                        query_state.setdefault(key, value)
                    # Extract filters from permalink dataMask
                    data_mask = permalink_state.get("dataMask")
                    if isinstance(data_mask, dict) and data_mask:
                        query_state["dataMask"] = data_mask
                        logger.reason(
                            "Extracted native filters from permalink dataMask",
                            extra={"filter_count": len(data_mask)},
                        )
                    resolved_dashboard_id = self._extract_dashboard_id_from_state(
                        permalink_state
                    )
                    resolved_chart_id = self._extract_chart_id_from_state(
                        permalink_state
                    )
                    if resolved_dashboard_id is not None:
                        dashboard_id = resolved_dashboard_id
                        unresolved_references = [
                            item
                            for item in unresolved_references
                            if item
                            != "dashboard_permalink_dataset_binding_unresolved"
                        ]
                        dataset_id, unresolved_references = (
                            self._recover_dataset_binding_from_dashboard(
                                dashboard_id=dashboard_id,
                                dataset_ref=dataset_ref,
                                unresolved_references=unresolved_references,
                            )
                        )
                        if dataset_id is not None:
                            dataset_ref = f"dataset:{dataset_id}"
                    elif resolved_chart_id is not None:
                        chart_id = resolved_chart_id
                        unresolved_references = [
                            item
                            for item in unresolved_references
                            if item
                            != "dashboard_permalink_dataset_binding_unresolved"
                        ]
                        try:
                            chart_payload = self.client.get_chart(chart_id)
                            chart_data = (
                                chart_payload.get("result", chart_payload)
                                if isinstance(chart_payload, dict)
                                else {}
                            )
                            datasource_id = chart_data.get("datasource_id")
                            if datasource_id is not None:
                                dataset_id = int(datasource_id)
                                dataset_ref = f"dataset:{dataset_id}"
                                logger.reason(
                                    "Recovered dataset reference from permalink chart context",
                                    extra={
                                        "chart_id": chart_id,
                                        "dataset_id": dataset_id,
                                    },
                                )
                            else:
                                unresolved_references.append(
                                    "chart_dataset_binding_unresolved"
                                )
                        except Exception as exc:
                            unresolved_references.append(
                                "chart_dataset_binding_unresolved"
                            )
                            logger.explore(
                                "Chart lookup failed during permalink recovery",
                                extra={"chart_id": chart_id, "error": str(exc)},
                            )
                else:
                    logger.explore(
                        "Dashboard permalink state was not a structured object",
                        extra={"permalink_key": dashboard_permalink_key},
                    )
            elif dashboard_id is not None or dashboard_ref is not None:
                resource_type = "dashboard"
                resolved_dashboard_ref = (
                    dashboard_id if dashboard_id is not None else dashboard_ref
                )
                if resolved_dashboard_ref is None:
                    raise ValueError("Dashboard reference could not be resolved")
                logger.reason(
                    "Resolving dashboard-bound dataset from Superset",
                    extra={"dashboard_ref": resolved_dashboard_ref},
                )
                # Resolve dashboard detail first — handles both numeric ID and slug,
                # ensuring dashboard_id is available for the native_filters_key fetch below.
                dashboard_detail = self.client.get_dashboard_detail(
                    resolved_dashboard_ref
                )
                resolved_dashboard_id = dashboard_detail.get("id")
                if resolved_dashboard_id is not None:
                    dashboard_id = int(resolved_dashboard_id)
                # Check for native_filters_key in query params and fetch filter state.
                # This must run AFTER dashboard_id is resolved from slug above.
                native_filters_key = query_params.get("native_filters_key", [None])[0]
                if native_filters_key and dashboard_id is not None:
                    try:
                        logger.reason(
                            "Fetching native filter state from Superset",
                            extra={
                                "dashboard_id": dashboard_id,
                                "filter_key": native_filters_key,
                            },
                        )
                        extracted = self.client.extract_native_filters_from_key(
                            dashboard_id, native_filters_key
                        )
                        data_mask = extracted.get("dataMask")
                        if isinstance(data_mask, dict) and data_mask:
                            query_state["native_filter_state"] = data_mask
                            logger.reason(
                                "Extracted native filter state from Superset via native_filters_key",
                                extra={"filter_count": len(data_mask)},
                            )
                        else:
                            logger.explore(
                                "Native filter state returned empty dataMask",
                                extra={
                                    "dashboard_id": dashboard_id,
                                    "filter_key": native_filters_key,
                                },
                            )
                    except Exception as exc:
                        logger.explore(
                            "Failed to fetch native filter state from Superset",
                            extra={
                                "dashboard_id": dashboard_id,
                                "filter_key": native_filters_key,
                                "error": str(exc),
                            },
                        )
                datasets = dashboard_detail.get("datasets") or []
                if datasets:
                    first_dataset = datasets[0]
                    resolved_dataset_id = first_dataset.get("id")
                    if resolved_dataset_id is not None:
                        dataset_id = int(resolved_dataset_id)
                        dataset_ref = f"dataset:{dataset_id}"
                        logger.reason(
                            "Recovered dataset reference from dashboard context",
                            extra={
                                "dashboard_id": dashboard_id,
                                "dataset_id": dataset_id,
                                "dataset_count": len(datasets),
                            },
                        )
                        if len(datasets) > 1:
                            partial_recovery = True
                            unresolved_references.append(
                                "multiple_dashboard_datasets"
                            )
                    else:
                        partial_recovery = True
                        unresolved_references.append("dashboard_dataset_id_missing")
                else:
                    partial_recovery = True
                    unresolved_references.append("dashboard_dataset_binding_missing")
            elif chart_id is not None:
                resource_type = "chart"
                partial_recovery = True
                unresolved_references.append("chart_dataset_binding_unresolved")
                dataset_ref = f"chart:{chart_id}"
                logger.reason(
                    "Accepted chart link with explicit partial recovery",
                    extra={"chart_id": chart_id},
                )
            else:
                logger.explore(
                    "Unsupported Superset link shape encountered",
                    extra={"path": parsed_url.path},
                )
                raise ValueError("Unsupported Superset link shape")
            dataset_payload: dict[str, Any] | None = None
            if dataset_id is not None:
                try:
                    dataset_payload = self.client.get_dataset_detail(dataset_id)
                    table_name = str(
                        dataset_payload.get("table_name") or ""
                    ).strip()
                    schema_name = str(
                        dataset_payload.get("schema") or ""
                    ).strip()
                    if table_name:
                        dataset_ref = (
                            f"{schema_name}.{table_name}"
                            if schema_name
                            else table_name
                        )
                        logger.reason(
                            "Canonicalized dataset reference from dataset detail",
                            extra={
                                "dataset_ref": dataset_ref,
                                "dataset_id": dataset_id,
                            },
                        )
                except Exception as exc:
                    partial_recovery = True
                    unresolved_references.append("dataset_detail_lookup_failed")
                    logger.explore(
                        "Dataset detail lookup failed during link parsing; keeping session usable",
                        extra={"dataset_id": dataset_id, "error": str(exc)},
                    )
            imported_filters = self._extract_imported_filters(query_state)
            result = SupersetParsedContext(
                source_url=normalized_link,
                dataset_ref=dataset_ref or "unresolved",
                dataset_id=dataset_id,
                dashboard_id=dashboard_id,
                chart_id=chart_id,
                resource_type=resource_type,
                query_state=query_state,
                imported_filters=imported_filters,
                unresolved_references=unresolved_references,
                partial_recovery=partial_recovery,
                dataset_payload=dataset_payload,
            )
            logger.reflect(
                "Superset link parsing completed",
                extra={
                    "dataset_ref": result.dataset_ref,
                    "dataset_id": result.dataset_id,
                    "dashboard_id": result.dashboard_id,
                    "chart_id": result.chart_id,
                    "partial_recovery": result.partial_recovery,
                    "unresolved_references": result.unresolved_references,
                    "imported_filters": len(result.imported_filters),
                },
            )
            return result
    # #endregion SupersetContextParsingMixin.parse_superset_link
    # #region SupersetContextParsingMixin._recover_dataset_binding_from_dashboard [TYPE Function] [C:3]
    # @PURPOSE: Recover a dataset binding from resolved dashboard context while preserving explicit unresolved markers.
    # @RELATION CALLS -> [EXT:method:SupersetClient.get_dashboard_detail]
    def _recover_dataset_binding_from_dashboard(
        self,
        dashboard_id: int,
        dataset_ref: str | None,
        unresolved_references: list[str],
    ) -> tuple[int | None, list[str]]:
        dashboard_detail = self.client.get_dashboard_detail(dashboard_id)
        datasets = dashboard_detail.get("datasets") or []
        if datasets:
            first_dataset = datasets[0]
            resolved_dataset_id = first_dataset.get("id")
            if resolved_dataset_id is not None:
                resolved_dataset = int(resolved_dataset_id)
                logger.reason(
                    "Recovered dataset reference from dashboard permalink context",
                    extra={
                        "dashboard_id": dashboard_id,
                        "dataset_id": resolved_dataset,
                        "dataset_count": len(datasets),
                        "dataset_ref": dataset_ref,
                    },
                )
                if (
                    len(datasets) > 1
                    and "multiple_dashboard_datasets" not in unresolved_references
                ):
                    unresolved_references.append("multiple_dashboard_datasets")
                return resolved_dataset, unresolved_references
            if "dashboard_dataset_id_missing" not in unresolved_references:
                unresolved_references.append("dashboard_dataset_id_missing")
            return None, unresolved_references
        if "dashboard_dataset_binding_missing" not in unresolved_references:
            unresolved_references.append("dashboard_dataset_binding_missing")
        return None, unresolved_references
    # #endregion SupersetContextParsingMixin._recover_dataset_binding_from_dashboard
# #endregion SupersetContextParsingMixin
