"""
Action Dispatcher für Alerts Agent.

Verteilt Aktionen an die entsprechenden Handler.
"""
import logging
from typing import Dict, Any, List, Optional
from datetime import datetime

from .base import ActionHandler, ActionResult, ActionType, AlertContext
from .email_action import EmailAction
from .webhook_action import WebhookAction
from .slack_action import SlackAction

logger = logging.getLogger(__name__)


class ActionDispatcher:
    """
    Zentrale Verteilung von Aktionen an Handler.

    Registriert Handler für verschiedene Aktionstypen und
    führt Aktionen basierend auf Regel-Konfigurationen aus.
    """

    def __init__(self):
        """Initialisiert den Dispatcher mit Standard-Handlern."""
        self._handlers: Dict[ActionType, ActionHandler] = {}

        # Standard-Handler registrieren
        self.register_handler(EmailAction())
        self.register_handler(WebhookAction())
        self.register_handler(SlackAction())

    def register_handler(self, handler: ActionHandler) -> None:
        """
        Registriert einen Action-Handler.

        Args:
            handler: Handler-Instanz
        """
        self._handlers[handler.action_type] = handler
        logger.debug(f"Registered action handler: {handler.action_type.value}")

    def get_handler(self, action_type: ActionType) -> Optional[ActionHandler]:
        """
        Gibt den Handler für einen Aktionstyp zurück.

        Args:
            action_type: Aktionstyp

        Returns:
            Handler oder None
        """
        return self._handlers.get(action_type)

    def list_handlers(self) -> List[str]:
        """Gibt Liste der registrierten Handler zurück."""
        return [at.value for at in self._handlers.keys()]

    async def dispatch(
        self,
        action_type: str,
        context: AlertContext,
        config: Dict[str, Any],
    ) -> ActionResult:
        """
        Führt eine Aktion aus.

        Args:
            action_type: Aktionstyp als String (email, webhook, slack)
            context: Alert-Kontext
            config: Aktionsspezifische Konfiguration

        Returns:
            ActionResult
        """
        try:
            # ActionType aus String
            at = ActionType(action_type.lower())
        except ValueError:
            return ActionResult(
                success=False,
                action_type=ActionType.WEBHOOK,  # Fallback
                message=f"Unbekannter Aktionstyp: {action_type}",
                error="Unknown action type",
            )

        handler = self.get_handler(at)

        if not handler:
            return ActionResult(
                success=False,
                action_type=at,
                message=f"Kein Handler für {action_type} registriert",
                error="No handler registered",
            )

        # Konfiguration validieren
        if not handler.validate_config(config):
            required = handler.get_required_config_fields()
            return ActionResult(
                success=False,
                action_type=at,
                message=f"Ungültige Konfiguration für {action_type}",
                error=f"Required fields: {required}",
            )

        # Aktion ausführen
        logger.info(f"Dispatching {action_type} action for alert {context.alert_id[:8]}")
        result = await handler.execute(context, config)

        return result

    async def dispatch_multiple(
        self,
        actions: List[Dict[str, Any]],
        context: AlertContext,
    ) -> List[ActionResult]:
        """
        Führt mehrere Aktionen aus.

        Args:
            actions: Liste von Aktionen [{type, config}, ...]
            context: Alert-Kontext

        Returns:
            Liste von ActionResults
        """
        results = []

        for action in actions:
            action_type = action.get("type", action.get("action_type", ""))
            config = action.get("config", action.get("action_config", {}))

            result = await self.dispatch(action_type, context, config)
            results.append(result)

        return results


# Singleton-Instanz
_dispatcher: Optional[ActionDispatcher] = None


def get_dispatcher() -> ActionDispatcher:
    """Gibt den globalen ActionDispatcher zurück."""
    global _dispatcher
    if _dispatcher is None:
        _dispatcher = ActionDispatcher()
    return _dispatcher


async def execute_action(
    action_type: str,
    alert_id: str,
    title: str,
    url: str,
    snippet: str,
    topic_name: str,
    config: Dict[str, Any],
    relevance_score: Optional[float] = None,
    relevance_decision: Optional[str] = None,
    matched_rule: Optional[str] = None,
    tags: Optional[List[str]] = None,
) -> ActionResult:
    """
    Convenience-Funktion zum Ausführen einer Aktion.

    Erstellt den Kontext und ruft den Dispatcher auf.
    """
    context = AlertContext(
        alert_id=alert_id,
        title=title,
        url=url,
        snippet=snippet,
        topic_name=topic_name,
        relevance_score=relevance_score,
        relevance_decision=relevance_decision,
        matched_rule=matched_rule,
        tags=tags or [],
    )

    dispatcher = get_dispatcher()
    return await dispatcher.dispatch(action_type, context, config)


async def execute_rule_actions(
    alert_id: str,
    title: str,
    url: str,
    snippet: str,
    topic_name: str,
    rule_action: str,
    rule_config: Dict[str, Any],
    rule_name: str,
) -> ActionResult:
    """
    Führt die Aktion einer gematschten Regel aus.

    Args:
        alert_id: Alert-ID
        title: Alert-Titel
        url: Alert-URL
        snippet: Alert-Snippet
        topic_name: Topic-Name
        rule_action: Aktionstyp der Regel
        rule_config: Aktions-Konfiguration
        rule_name: Name der Regel

    Returns:
        ActionResult
    """
    # Nur externe Aktionen (email, webhook, slack) hier behandeln
    # keep/drop/tag werden direkt von der Rule Engine behandelt
    if rule_action not in ["email", "webhook", "slack"]:
        return ActionResult(
            success=True,
            action_type=ActionType.TAG,  # Dummy
            message=f"Interne Aktion {rule_action} von Rule Engine behandelt",
        )

    return await execute_action(
        action_type=rule_action,
        alert_id=alert_id,
        title=title,
        url=url,
        snippet=snippet,
        topic_name=topic_name,
        config=rule_config,
        matched_rule=rule_name,
    )
