"""Topic → payload model registry.

Maps each :class:`~broker_core.topics.enums.Topic` to its expected
Pydantic payload model so consumers can validate incoming messages
against the correct schema at runtime.
"""

from __future__ import annotations

from pydantic import BaseModel

from .enums import Topic
from .models.errors import PipelineErrorPayload
from .models.backfill import BackfillJobPayload
from .models.telegram_crawler import CrawlerEventPayload, TelegramCrawlMetricPayload
from .models.telegram import (
    TelegramAnalyzeReadyPayload,
    TelegramMessagePayload,
    TelegramParsedPayload,
)

# =========================================================================
# Topic → Payload mapping
# =========================================================================

TOPIC_PAYLOAD_MAP: dict[Topic, type[BaseModel]] = {
    # -- RAW ---------------------------------------------------------
    Topic.TELEGRAM_MESSAGE_RAW_READY: TelegramMessagePayload,
    Topic.TELEGRAM_MESSAGE_RAW_PERSISTED: TelegramMessagePayload,
    Topic.TELEGRAM_MESSAGE_RAW_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_RAW_DEAD: PipelineErrorPayload,

    # -- PARSE -------------------------------------------------------
    Topic.TELEGRAM_MESSAGE_PARSE_READY: TelegramParsedPayload,
    Topic.TELEGRAM_MESSAGE_PARSE_PERSISTED: TelegramParsedPayload,
    Topic.TELEGRAM_MESSAGE_PARSE_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_PARSE_DEAD: PipelineErrorPayload,

    # -- ANALYZE -----------------------------------------------------
    Topic.TELEGRAM_MESSAGE_ANALYZE_READY: TelegramAnalyzeReadyPayload,
    Topic.TELEGRAM_MESSAGE_ANALYZE_PERSISTED: TelegramParsedPayload,
    Topic.TELEGRAM_MESSAGE_ANALYZE_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_ANALYZE_DEAD: PipelineErrorPayload,

    # -- MEDIA -------------------------------------------------------
    Topic.TELEGRAM_MESSAGE_MEDIA_READY: TelegramParsedPayload,
    Topic.TELEGRAM_MESSAGE_MEDIA_PERSISTED: TelegramParsedPayload,
    Topic.TELEGRAM_MESSAGE_MEDIA_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_MEDIA_DEAD: PipelineErrorPayload,

    # -- PERSISTENCE -------------------------------------------------
    Topic.TELEGRAM_MESSAGE_PERSISTENCE_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_PERSISTENCE_DEAD: PipelineErrorPayload,

    # -- METRICS -----------------------------------------------------
    Topic.TELEGRAM_MESSAGE_METRICS_READY: TelegramCrawlMetricPayload,
    Topic.TELEGRAM_MESSAGE_METRICS_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_METRICS_DEAD: PipelineErrorPayload,

    # -- EVENTS ------------------------------------------------------
    Topic.TELEGRAM_MESSAGE_EVENTS_READY: CrawlerEventPayload,
    Topic.TELEGRAM_MESSAGE_EVENTS_FAILED: PipelineErrorPayload,
    Topic.TELEGRAM_MESSAGE_EVENTS_DEAD: PipelineErrorPayload,

    # -- BACKFILL ----------------------------------------------------
    Topic.TELEGRAM_BACKFILL_JOB_READY: BackfillJobPayload,
}
"""Maps each topic to its expected payload model.

**Registration checklist for new topics**:

1. Add the topic to :class:`Topic` in :mod:`~broker_core.topics.enums`.
2. Create a payload model in :mod:`~broker_core.topics.models`.
3. Add a ``Topic → Model`` entry here.
4. Re-export from :mod:`~broker_core.topics` and
   :mod:`broker_core`.
"""


def get_payload_model(topic: str) -> type[BaseModel] | None:
    """Resolve a topic name (from a Kafka message) to its payload model.

    Returns ``None`` for unknown topics so callers can fall back to
    raw ``dict`` passthrough.
    """
    try:
        return TOPIC_PAYLOAD_MAP.get(Topic(topic))
    except ValueError:
        return None
