"""
Project-registered handlers for job push: enrich or filter payload before send.

Handlers are called in order; if any returns None, the event is not sent.
See docs/plans/bidirectional_job_push/07_project_handlers_hooks.md.

Author: Vasiliy Zdanovskiy
email: vasilyvz@gmail.com
"""

from __future__ import annotations

from typing import Any, Awaitable, Callable, Dict, List, Union

# Handler: (job_id, payload) -> dict | None (or awaitable)
JobPushHandler = Callable[[str, Dict[str, Any]], Union[Dict[str, Any], None, Awaitable[Dict[str, Any]], Awaitable[None]]]
_handlers: List[JobPushHandler] = []


def register_job_push_handler(handler: JobPushHandler) -> None:
    """Register a handler to be run before sending a job push event. Called at app startup."""
    _handlers.append(handler)


def get_job_push_handlers() -> List[JobPushHandler]:
    """Return snapshot of registered handlers (for notifier / step 06)."""
    return list(_handlers)


async def run_job_push_handlers(
    job_id: str, payload: Dict[str, Any]
) -> Dict[str, Any] | None:
    """
    Run handlers in order. If any returns None, return None (do not send).
    Otherwise return the last returned dict (or original payload if none returned dict).
    """
    current: Dict[str, Any] | None = payload
    for h in get_job_push_handlers():
        out = h(job_id, current if current is not None else payload)
        if hasattr(out, "__await__"):
            out = await out
        if out is None:
            return None
        current = out
    return current
