from abc import ABC, abstractmethod
from typing import Any

from messagebus import Event, MessageBus


class Sender(ABC):
    """Contract for sending responses to the message bus."""

    @abstractmethod
    def send(self, message_bus: MessageBus, original_event: Event, data: Any, original_payload: dict) -> None:
        """Sends a success response.

        Args:
            message_bus: Bus used to dispatch the message.
            original_event: Original event received by the processor.
            data: Already serialized data.
            original_payload: Original message payload (contains report-id, sync, response-upload-url).
        """

    def send_error(
        self, message_bus: MessageBus, original_event: Event, data: dict | str, original_payload: dict
    ) -> None:
        """Sends an error response for an exception raised after parsing (business step).

        Defaults to a no-op so senders that don't report business errors need not override it.

        Args:
            message_bus: Bus used to dispatch the message.
            original_event: Original event received by the processor.
            data: Already serialized error response.
            original_payload: Original message payload (contains sync to determine reply vs publish).
        """

    def send_parser_error(
        self, message_bus: MessageBus, original_event: Event, data: dict | str, original_payload: dict
    ) -> None:
        """Sends an error response for an exception raised during parsing.

        Defaults to a no-op so senders that don't report parse errors need not override it.

        Args:
            message_bus: Bus used to dispatch the message.
            original_event: Original event received by the processor.
            data: Already serialized error response.
            original_payload: Original message payload (may be empty when parsing failed before assignment).
        """
