"""Automation Event Bus subscriptions rule (async, non-blocking).
- Never evaluate conditions or execute actions in-process — that is the
  executor's job running in the worker.

This keeps web-request latency unaffected (Automation principle 3.1.3).
"""

from __future__ import annotations

import uuid
from typing import Any

import structlog

from simorgh.apps.automation.builtin_actions import register_builtin_actions
from simorgh.apps.events.bus import subscribe_all

_log = structlog.get_logger("simorgh.automation.events")

# 1. Register built-in actions.
register_builtin_actions()


# 2. Subscribe to every event — dispatch Celery tasks for matching rules.
@subscribe_all
def _automation_catchall_handler(event_name: str, payload: dict[str, Any]) -> None:
    """Fan out active event-triggered rules to Celery workers.

    Called synchronously inside the Event Bus dispatch loop, so this
    function must be fast (only DB reads + task.delay calls).
    """
    from simorgh.apps.automation.models import AutomationRule, TriggerType
    from simorgh.apps.automation.tasks import execute_automation_rule_task

    rules = AutomationRule.objects.filter(
        is_active=True,
        trigger_type=TriggerType.EVENT,
        trigger_event=event_name,
    ).values_list("pk", "tenant_id")

    if not rules:
        return

    for rule_id, _tenant_id in rules:
        idem_key = str(uuid.uuid4())
        try:
            execute_automation_rule_task.delay(
                rule_id,
                payload,
                trigger_event=event_name,
                idempotency_key=idem_key,
            )
        except Exception as exc:
            # Celery unavailable (dev without broker) — log and continue.
            _log.warning(
                "automation.event.dispatch_failed",
                rule_id=rule_id,
                event_name=event_name,
                error=str(exc),
            )


# 3. Subscribe to every event — fan out to active WebhookEndpoints.
@subscribe_all
def _webhook_catchall_handler(event_name: str, payload: dict[str, Any]) -> None:
    """Deliver matching outbound webhooks for every event.

    For each active ``WebhookEndpoint`` whose ``events`` list contains
    *event_name*, create a ``WebhookDelivery`` and enqueue
    ``send_webhook_task``.  Failures are isolated per-endpoint.
    """
    from simorgh.apps.automation.models import WebhookEndpoint
    from simorgh.apps.automation.webhook_service import deliver_webhook

    endpoints = WebhookEndpoint.objects.filter(is_active=True)
    for endpoint in endpoints:
        if event_name in (endpoint.events or []):
            try:
                deliver_webhook(endpoint, event_name, payload)
            except Exception as exc:
                _log.warning(
                    "webhook.event.trigger_failed",
                    endpoint_id=endpoint.pk,
                    event_name=event_name,
                    error=str(exc),
                )

