"""Streaming ingestion service for Kafka/Pub-Sub style data ingestion.

Provides an asynchronous pipeline for consuming racing data from
message brokers, enabling near-real-time rating updates.
"""

from __future__ import annotations

from collections.abc import Callable
from enum import StrEnum
from typing import Any


class MessageSource(StrEnum):
    """Supported streaming message sources."""

    KAFKA = "kafka"
    REDIS_PUBSUB = "redis_pubsub"
    RABBITMQ = "rabbitmq"
    WEBHOOK = "webhook"


class StreamingIngestionService:
    """Ingests racing data via streaming message brokers.

    Supports consuming race results, runner updates, and meeting
    information from Kafka, Redis Pub/Sub, or other brokers for
    near-real-time processing.
    """

    def __init__(
        self,
        source: MessageSource | str = MessageSource.KAFKA,
        config: dict[str, Any] | None = None,
    ) -> None:
        """Initialize the streaming ingestion service.

        Args:
            source: Message source type.
            config: Source-specific configuration dict (e.g.,
                bootstrap_servers, topic, group_id for Kafka).
        """
        self.source = MessageSource(source)
        self.config = config or {}
        self._handlers: dict[str, list[Callable]] = {}
        self._running = False

    def register_handler(
        self,
        topic: str,
        handler: Callable[[dict[str, Any]], None],
    ) -> None:
        """Register a handler function for a given topic.

        Args:
            topic: Message topic/channel to subscribe to.
            handler: Callable that accepts a message payload dict.
        """
        self._handlers.setdefault(topic, []).append(handler)

    async def start(self) -> None:
        """Start consuming messages from the configured source.

        Connects to the broker and begins the main event loop,
        dispatching messages to registered handlers.
        """
        raise NotImplementedError

    async def stop(self) -> None:
        """Gracefully stop the ingestion service.

        Closes broker connection and waits for in-flight messages
        to complete processing.
        """
        raise NotImplementedError

    async def publish(self, topic: str, message: dict[str, Any]) -> None:
        """Publish a message to the streaming source.

        Useful for re-publishing processed events for downstream
        consumers (e.g., rating updates).

        Args:
            topic: Topic/channel to publish to.
            message: Message payload.
        """
        raise NotImplementedError

    @property
    def is_running(self) -> bool:
        """Whether the service is currently consuming messages."""
        return self._running
