# #region MapperPluginModule [TYPE Module] [SEMANTICS mapper, dataset, column, sqllab, excel, mapping]
# @BRIEF Implements a plugin for mapping dataset columns using Superset SQL Lab or Excel files.
# @LAYER Plugin
# @BRIEF Plugin for dataset column mapping. Inherits PluginBase.
# @RELATION DEPENDS_ON -> [TaskContext]

from typing import Any

from ..core.logger import belief_scope, logger
from ..core.plugin_base import PluginBase
from ..core.superset_client import SupersetClient
from ..core.task_manager.context import TaskContext
from ..core.utils.dataset_mapper import DatasetMapper


# #region MapperPlugin [TYPE Class]
# @BRIEF Plugin for mapping dataset columns verbose names.
class MapperPlugin(PluginBase):
    """
    Plugin for mapping dataset columns verbose names.
    """

    @property
    # region id [TYPE Function]
    # @PURPOSE: Returns the unique identifier for the mapper plugin.
    # @PRE  Plugin instance exists.
    # @POST  Returns string ID.
    # @RETURN  str - "dataset-mapper"
    def id(self) -> str:
        with belief_scope("id"):
            return "dataset-mapper"
    # endregion id

    @property
    # region name [TYPE Function]
    # @PURPOSE: Returns the human-readable name of the mapper plugin.
    # @PRE  Plugin instance exists.
    # @POST  Returns string name.
    # @RETURN  str - Plugin name.
    def name(self) -> str:
        with belief_scope("name"):
            return "Dataset Mapper"
    # endregion name

    @property
    # region description [TYPE Function]
    # @PURPOSE: Returns a description of the mapper plugin.
    # @PRE  Plugin instance exists.
    # @POST  Returns string description.
    # @RETURN  str - Plugin description.
    def description(self) -> str:
        with belief_scope("description"):
            return "Map dataset column verbose names using Superset SQL Lab or Excel files."
    # endregion description

    @property
    # region version [TYPE Function]
    # @PURPOSE: Returns the version of the mapper plugin.
    # @PRE  Plugin instance exists.
    # @POST  Returns string version.
    # @RETURN  str - "1.0.0"
    def version(self) -> str:
        with belief_scope("version"):
            return "1.0.0"
    # endregion version

    @property
    # region ui_route [TYPE Function]
    # @PURPOSE: Returns the frontend route for the mapper plugin.
    # @RETURN  str - "/tools/mapper"
    def ui_route(self) -> str:
        with belief_scope("ui_route"):
            return "/tools/mapper"
    # endregion ui_route

    # region get_schema [TYPE Function]
    # @PURPOSE: Returns the JSON schema for the mapper plugin parameters.
    # @PRE  Plugin instance exists.
    # @POST  Returns dictionary schema.
    # @RETURN  Dict[str, Any] - JSON schema.
    def get_schema(self) -> dict[str, Any]:
        with belief_scope("get_schema"):
            return {
            "type": "object",
            "properties": {
                "env": {
                    "type": "string",
                    "title": "Environment",
                    "description": "The Superset environment (e.g., 'dev')."
                },
                "dataset_id": {
                    "type": "integer",
                    "title": "Dataset ID",
                    "description": "The ID of the dataset to update."
                },
                "source": {
                    "type": "string",
                    "title": "Mapping Source",
                    "enum": ["sqllab", "excel"],
                    "default": "sqllab"
                },
                "database_id": {
                    "type": "integer",
                    "title": "Superset Database ID",
                    "description": "Target database ID in Superset (for sqllab source)."
                },
                "sql_query": {
                    "type": "string",
                    "title": "SQL Query",
                    "description": "Custom SQL query returning column_name and verbose_name columns. Default: information_schema.columns.",
                    "default": ""
                },
                "excel_path": {
                    "type": "string",
                    "title": "Excel Path",
                    "description": "Path to the Excel file (for excel source)."
                }
            },
            "required": ["env", "dataset_id", "source"]
        }
    # endregion get_schema

    # region execute [TYPE Function]
    # @PURPOSE: Executes the dataset mapping logic with TaskContext support.
    # @PARAM  params (Dict[str, Any]) - Mapping parameters.
    # @PARAM  context (Optional[TaskContext]) - Task context for logging with source attribution.
    # @PRE  Params contain valid 'env', 'dataset_id', and 'source'. params must be a dictionary.
    # @POST  Updates the dataset in Superset.
    # @RETURN  Dict[str, Any] - Execution status.
    async def execute(self, params: dict[str, Any], context: TaskContext | None = None) -> dict[str, Any]:
        with belief_scope("execute"):
            env_name = params.get("env")
            dataset_id = params.get("dataset_id")
            source = params.get("source")

            # Use TaskContext logger if available, otherwise fall back to app logger
            log = context.logger if context else logger

            # Create sub-loggers for different components
            superset_log = log.with_source("superset_api") if context else log

            if not env_name or dataset_id is None or not source:
                log.error("Missing required parameters: env, dataset_id, source")
                raise ValueError("Missing required parameters: env, dataset_id, source")

            # Get config and initialize client
            from ..dependencies import get_config_manager
            config_manager = get_config_manager()
            env_config = config_manager.get_environment(env_name)
            if not env_config:
                log.error(f"Environment '{env_name}' not found in configuration.")
                raise ValueError(f"Environment '{env_name}' not found in configuration.")

            client = SupersetClient(env_config)
            client.authenticate()

            log.info(f"Starting mapping for dataset {dataset_id} in {env_name}")

            mapper = DatasetMapper()

            try:
                if source == "sqllab":
                    # Use Superset SQL Lab to query database metadata
                    from ..plugins.translate.superset_executor import SupersetSqlLabExecutor
                    executor = SupersetSqlLabExecutor(config_manager, env_name)
                    database_id = params.get("database_id")
                    if not database_id:
                        log.error("database_id is required for sqllab source.")
                        raise ValueError("database_id is required for sqllab source.")
                    executor.resolve_database_id(target_database_id=str(database_id))

                    mapper.run_mapping(
                        superset_client=client,
                        dataset_id=dataset_id,
                        source="sqllab",
                        sqllab_executor=executor,
                        database_id=database_id,
                        sql_query=params.get("sql_query"),
                    )
                else:
                    # Excel source
                    mapper.run_mapping(
                        superset_client=client,
                        dataset_id=dataset_id,
                        source="excel",
                        excel_path=params.get("excel_path") or params.get("file_data")
                    )
                superset_log.info(f"Mapping completed for dataset {dataset_id}")
                return {"status": "success", "dataset_id": dataset_id}
            except Exception as e:
                log.error(f"Mapping failed: {e}")
                raise
    # endregion execute

# #endregion MapperPlugin
# #endregion MapperPluginModule
