"""Abstract base class for message channels."""

from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Optional


@dataclass
class ChannelHealth:
    ok: bool
    message: str = ""


@dataclass
class SendResult:
    ok: bool
    question_msg_id: Optional[str] = None
    raw_response: Optional[dict[str, Any]] = None
    error: Optional[str] = None


@dataclass
class Reply:
    question_msg_id: str
    content: Any
    sender_name: Optional[str] = None
    msg_time: Optional[datetime] = None
    raw_message: Optional[dict[str, Any]] = None


class EvalChannel(ABC):
    """Abstract message channel used to interact with an evaluation target.

    All methods are async so push-based channels (WebSocket, SSE) and
    poll-based channels (REST) share the same interface.
    """

    @abstractmethod
    async def health_check(self) -> ChannelHealth:
        """Verify the channel can reach the target."""
        ...

    @abstractmethod
    async def send(self, content: str, **kwargs: Any) -> SendResult:
        """Send a message to the target and return its question message id."""
        ...

    @abstractmethod
    async def poll_reply(
        self,
        question_msg_id: str,
        timeout: float = 30.0,
        poll_interval: float = 1.0,
    ) -> Optional[Reply]:
        """Wait for a reply to a previously sent message.

        Implementations may poll (REST) or await a push event (WebSocket).
        """
        ...
