"""Event-driven hook system for extensibility."""

from __future__ import annotations

import logging
from collections import defaultdict
from typing import Any, Callable

logger = logging.getLogger(__name__)


class HookManager:
    """Pre/post hooks on NEUROVAULT operations."""

    VALID_EVENTS = {
        "pre_ingest",
        "post_ingest",
        "pre_recall",
        "post_recall",
        "pre_consolidate",
        "post_consolidate",
        "pre_predict",
        "post_predict",
        "sensor_start",
        "sensor_stop",
        "plugin_load",
        "plugin_unload",
        "memory_decay",
        "memory_promote",
    }

    def __init__(self):
        self._hooks: dict[str, list[Callable]] = defaultdict(list)

    def register(self, event: str, callback: Callable) -> None:
        """Register a hook callback for an event."""
        if event not in self.VALID_EVENTS:
            raise ValueError(f"Unknown event: {event}. Valid: {self.VALID_EVENTS}")
        self._hooks[event].append(callback)
        logger.debug("Registered hook for %s", event)

    def unregister(self, event: str, callback: Callable) -> None:
        """Remove a previously registered hook callback."""
        self._hooks[event] = [h for h in self._hooks[event] if h is not callback]

    async def run(self, event: str, *args, **kwargs) -> list[Any]:
        """Execute all hooks for an event."""
        results: list[Any] = []
        for hook in self._hooks.get(event, []):
            try:
                result = hook(*args, **kwargs)
                if hasattr(result, "__await__"):
                    result = await result
                results.append(result)
            except Exception as exc:
                logger.warning("Hook error on %s: %s", event, exc)
        return results

    def run_sync(self, event: str, *args, **kwargs) -> list[Any]:
        """Synchronous version of run for non-async contexts."""
        results: list[Any] = []
        for hook in self._hooks.get(event, []):
            try:
                results.append(hook(*args, **kwargs))
            except Exception as exc:
                logger.warning("Hook error on %s: %s", event, exc)
        return results
