"""Abstract base classes for A2A transport."""

from __future__ import annotations

from abc import ABC, abstractmethod
from collections.abc import AsyncIterator


class Connection(ABC):
    """An authenticated, encrypted bidirectional channel to a peer."""

    @property
    @abstractmethod
    def peer_id(self) -> str:
        """The remote peer's PeerID (verified via handshake)."""
        ...

    @property
    @abstractmethod
    def remote_addr(self) -> str:
        """The remote address (for logging/diagnostics)."""
        ...

    @property
    @abstractmethod
    def is_open(self) -> bool:
        """Whether the connection is still open."""
        ...

    @abstractmethod
    async def send(self, data: bytes) -> None:
        """Send raw bytes (already encrypted at protocol level)."""
        ...

    @abstractmethod
    async def recv(self) -> bytes:
        """Receive raw bytes. Raises ConnectionError on close."""
        ...

    @abstractmethod
    async def close(self) -> None:
        """Gracefully close the connection."""
        ...


class Transport(ABC):
    """Listens for inbound connections and initiates outbound ones."""

    @abstractmethod
    async def listen(self, host: str, port: int) -> AsyncIterator[Connection]:
        """Accept incoming connections. Yields Connection objects."""
        ...

    @abstractmethod
    async def connect(self, addr: str) -> Connection:
        """Connect to a remote address. Returns an established Connection."""
        ...

    @abstractmethod
    async def shutdown(self) -> None:
        """Stop listening and close all connections."""
        ...
