"""Pipeline handler registry system.

This module provides a centralized registry for pipeline step handlers.
Handlers are functions that process specific step types (e.g., "input.file",
"decoder.uart") and return outputs that can be used by subsequent steps.

Handler Signature:
    All handlers must follow this signature:

    def handler(inputs: dict[str, Any], params: dict[str, Any], step_name: str) -> dict[str, Any]:
        '''Handler for step type.

        Args:
            inputs: Input data from previous steps
            params: Step parameters from YAML
            step_name: Name of step being executed (for error reporting)

        Returns:
            Dictionary of outputs to pass to next steps

        Raises:
            PipelineExecutionError: If step execution fails
        '''

Example:
    >>> from oscura.pipeline.handlers import register_handler
    >>>
    >>> @register_handler("custom.step")
    >>> def handle_custom(inputs: dict[str, Any], params: dict[str, Any], step_name: str) -> dict[str, Any]:
    ...     result = do_custom_processing(inputs, params)
    ...     return {"result": result}
    >>>
    >>> # Auto-register all handlers
    >>> from oscura.core.config.pipeline import Pipeline
    >>> from oscura.pipeline.handlers import register_all_handlers
    >>>
    >>> pipeline = Pipeline.load("analysis.yaml")
    >>> register_all_handlers(pipeline)
    >>> results = pipeline.execute()
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from collections.abc import Callable

    from oscura.core.config.pipeline import Pipeline


# Global handler registry
_HANDLER_REGISTRY: dict[str, Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]]] = {}


def register_handler(
    step_type: str,
) -> Callable[
    [Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]]],
    Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]],
]:
    """Decorator to register a handler for a step type.

    Args:
        step_type: Step type identifier (e.g., "input.file", "decoder.uart")

    Returns:
        Decorator function

    Example:
        >>> @register_handler("input.file")
        >>> def handle_input_file(inputs: dict[str, Any], params: dict[str, Any], step_name: str) -> dict[str, Any]:
        ...     # Load file and return trace
        ...     return {"trace": loaded_trace}
    """

    def decorator(
        func: Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]],
    ) -> Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]]:
        """Register handler function."""
        _HANDLER_REGISTRY[step_type] = func
        return func

    return decorator


def get_handler(
    step_type: str,
) -> Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]] | None:
    """Get handler for a step type.

    Args:
        step_type: Step type identifier

    Returns:
        Handler function or None if not found
    """
    return _HANDLER_REGISTRY.get(step_type)


def get_all_handlers() -> dict[
    str, Callable[[dict[str, Any], dict[str, Any], str], dict[str, Any]]
]:
    """Get all registered handlers.

    Returns:
        Dictionary mapping step types to handler functions
    """
    return _HANDLER_REGISTRY.copy()


def list_handler_types() -> list[str]:
    """List all registered handler types.

    Returns:
        Sorted list of step type identifiers
    """
    return sorted(_HANDLER_REGISTRY.keys())


def register_all_handlers(pipeline: Pipeline) -> None:
    """Register all handlers with a pipeline.

    This is the main entry point for setting up a pipeline with all
    available handlers. Import this after importing handler modules.

    Args:
        pipeline: Pipeline instance to register handlers with

    Example:
        >>> from oscura.core.config.pipeline import Pipeline
        >>> from oscura.pipeline.handlers import register_all_handlers
        >>>
        >>> pipeline = Pipeline.load("analysis.yaml")
        >>> register_all_handlers(pipeline)
        >>> results = pipeline.execute()
    """
    for step_type, handler in _HANDLER_REGISTRY.items():
        pipeline.register_handler(step_type, handler)


# Import all handler modules to trigger registration
# These imports must come after the registry is defined
from oscura.pipeline.handlers import (
    analyzers,
    decoders,
    exporters,
    filters,
    loaders,
    transforms,
)

__all__ = [
    "analyzers",
    "decoders",
    "exporters",
    "filters",
    "get_all_handlers",
    "get_handler",
    "list_handler_types",
    "loaders",
    "register_all_handlers",
    "register_handler",
    "transforms",
]
