"""
Event Bridge — Unified event stream for OpenMemo OpenClaw Adapter.

Captures all system events and routes them to:
  → Aggregator (FeedbackStore)
  → Insight Engine (ActivationStore)
  → Any registered subscriber

Supported events:
  on_task_start      — task begins
  on_memory_recall   — memories retrieved
  on_memory_inject   — memories injected into context
  on_workflow_adopt  — workflow reused
  on_task_complete   — task finished
  on_memory_store    — memory written
  on_policy_block    — memory blocked by policy

Performance target: event processing < 20ms
"""

import time
import threading
import logging
from typing import Callable, Dict, List, Optional

logger = logging.getLogger("openmemo_openclaw")

EVENT_TYPES = frozenset([
    "on_task_start",
    "on_memory_recall",
    "on_memory_inject",
    "on_workflow_adopt",
    "on_task_complete",
    "on_memory_store",
    "on_policy_block",
])

MAX_LOG_SIZE = 500


class EventBridge:
    """
    Lightweight pub-sub event bus.

    Usage:
        bridge = EventBridge()
        bridge.subscribe("on_task_complete", my_handler)
        bridge.emit("on_task_complete", task_id="t1", metadata={"summary": "..."})
    """

    def __init__(self):
        self._lock = threading.Lock()
        self._handlers: Dict[str, List[Callable]] = {et: [] for et in EVENT_TYPES}
        self._event_log: List[dict] = []
        self._counters: Dict[str, int] = {et: 0 for et in EVENT_TYPES}

    def subscribe(self, event_type: str, handler: Callable) -> None:
        """Register a handler for an event type."""
        if event_type not in EVENT_TYPES:
            logger.warning("[event_bridge] unknown event_type=%s", event_type)
            return
        with self._lock:
            self._handlers[event_type].append(handler)

    def subscribe_all(self, handler: Callable) -> None:
        """Register a handler for every event type."""
        for et in EVENT_TYPES:
            self.subscribe(et, handler)

    def emit(
        self,
        event_type: str,
        task_id: str = "",
        metadata: Optional[dict] = None,
    ) -> dict:
        """
        Emit an event. Calls all registered handlers synchronously.
        Returns the event dict.

        Performance target: < 20ms per emit.
        """
        event = {
            "event_type": event_type,
            "task_id": task_id,
            "timestamp": int(time.time() * 1000),
            "metadata": metadata or {},
        }

        handlers = []
        with self._lock:
            handlers = list(self._handlers.get(event_type, []))
            self._counters[event_type] = self._counters.get(event_type, 0) + 1
            self._event_log.append(event)
            if len(self._event_log) > MAX_LOG_SIZE:
                self._event_log = self._event_log[-MAX_LOG_SIZE:]

        for handler in handlers:
            try:
                handler(event)
            except Exception as exc:
                logger.warning("[event_bridge] handler error for %s: %s", event_type, exc)

        logger.debug("[event_bridge] emit=%s task=%s", event_type, task_id)
        return event

    def get_recent(self, limit: int = 50, event_type: Optional[str] = None) -> List[dict]:
        """Return recent events, optionally filtered by type."""
        with self._lock:
            events = list(self._event_log)
        if event_type:
            events = [e for e in events if e["event_type"] == event_type]
        return events[-limit:]

    def get_stats(self) -> dict:
        """Return per-type event counters."""
        with self._lock:
            return dict(self._counters)

    def clear(self) -> None:
        with self._lock:
            self._event_log.clear()
            self._counters = {et: 0 for et in EVENT_TYPES}
