# #region MaintenanceBannerPlugin [C:4] [TYPE Module] [SEMANTICS plugin, maintenance, banner, execution, task]
# @BRIEF TaskManager plugin for executing maintenance banner operations (start, end, end-all).
#   Dispatches to MaintenanceService based on operation type in params.
# @LAYER Plugin
# @RELATION IMPLEMENTS -> [PluginBase]
# @RELATION DEPENDS_ON -> [EXT:frontend:MaintenanceServiceModule]
# @RELATION DEPENDS_ON -> [SupersetClient]
# @RELATION DEPENDS_ON -> [TaskContext]
# @INVARIANT TaskManager executes this plugin with params containing operation and event_id.

from typing import Any

from ..core.database import SessionLocal
from ..core.logger import belief_scope, logger as app_logger
from ..core.plugin_base import PluginBase
from ..core.superset_client import SupersetClient
from ..core.task_manager.context import TaskContext
from ..dependencies import get_config_manager
from ..models.maintenance import MaintenanceSettings
from ..services.maintenance import end_all_maintenance, end_maintenance, start_maintenance


# #region MaintenanceBannerPlugin [C:4] [TYPE Class]
# @BRIEF Plugin for executing maintenance banner operations asynchronously via TaskManager.
# @RELATION CALLS -> [start_maintenance]
# @RELATION CALLS -> [end_maintenance]
# @RELATION CALLS -> [end_all_maintenance]
class MaintenanceBannerPlugin(PluginBase):
    """TaskManager plugin for maintenance banner operations."""

    # #region id [TYPE Property]
    @property
    def id(self) -> str:
        return "maintenance_banner_apply"
    # #endregion id

    # #region name [TYPE Property]
    @property
    def name(self) -> str:
        return "Maintenance Banner"
    # #endregion name

    # #region description [TYPE Property]
    @property
    def description(self) -> str:
        return "Applies or removes maintenance banners on Superset dashboards."
    # #endregion description

    # #region version [TYPE Property]
    @property
    def version(self) -> str:
        return "1.0.0"
    # #endregion version

    # #region ui_route [TYPE Property]
    @property
    def ui_route(self) -> str:
        return ""  # No UI route — async-only
    # #endregion ui_route

    # #region get_schema [TYPE Function]
    def get_schema(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "operation": {
                    "type": "string",
                    "enum": ["start", "end", "end_all"],
                    "title": "Operation",
                },
                "event_id": {
                    "type": "string",
                    "title": "Maintenance Event ID",
                },
                "environment_id": {
                    "type": "string",
                    "title": "Target Environment ID",
                },
            },
            "required": ["operation"],
        }
    # #endregion get_schema

    # #region execute [TYPE Function] [C:4]
    # @BRIEF Execute maintenance operation based on params.operation.
    # @PARAM params contains: operation (start|end|end_all), event_id, environment_id.
    # @PARAM context TaskContext for logging.
    # @PRE DB and Superset available.
    # @POST Operation completed. Results returned as dict.
    # @SIDE_EFFECT Modifies Superset dashboards, writes DB rows.
    async def execute(
        self,
        params: dict[str, Any],
        context: TaskContext | None = None,
    ) -> dict[str, Any]:
        with belief_scope("MaintenanceBannerPlugin.execute"):
            operation = params.get("operation", "start")
            event_id = params.get("event_id", "")
            environment_id = params.get("environment_id", "")

            app_logger.reason(
                "Executing maintenance operation",
                extra={
                    "operation": operation,
                    "event_id": event_id,
                    "environment_id": environment_id,
                },
            )

            db = SessionLocal()
            try:
                # Resolve environment
                if not environment_id:
                    settings = db.query(MaintenanceSettings).filter(
                        MaintenanceSettings.id == "default"
                    ).first()
                    if settings:
                        environment_id = settings.target_environment_id

                if not environment_id:
                    config_manager = get_config_manager()
                    envs = config_manager.get_environments()
                    if envs:
                        environment_id = envs[0].id

                env = None
                config_manager = get_config_manager()
                for e in config_manager.get_environments():
                    if e.id == environment_id:
                        env = e
                        break

                if not env:
                    app_logger.explore(
                        "Environment not found",
                        extra={"environment_id": environment_id},
                        error="EnvironmentNotFound",
                    )
                    return {"status": "failed", "error": f"Environment {environment_id} not found"}

                superset_client = SupersetClient(env)

                if operation == "start":
                    if not event_id:
                        return {"status": "failed", "error": "event_id required for start"}
                    result = start_maintenance(event_id, db, superset_client)
                elif operation == "end":
                    if not event_id:
                        return {"status": "failed", "error": "event_id required for end"}
                    result = end_maintenance(event_id, db, superset_client)
                elif operation == "end_all":
                    result = end_all_maintenance(db, superset_client)
                else:
                    result = {"status": "failed", "error": f"Unknown operation: {operation}"}

                db.commit()
                app_logger.reflect(
                    "Maintenance operation completed",
                    extra={"operation": operation, "result": result},
                )
                return result

            except Exception as e:
                db.rollback()
                app_logger.explore(
                    "Maintenance operation failed",
                    extra={"operation": operation, "event_id": event_id},
                    error=str(e),
                )
                return {"status": "failed", "error": str(e)}
            finally:
                db.close()
    # #endregion execute
# #endregion MaintenanceBannerPlugin

# #endregion MaintenanceBannerPlugin
