"""
WebTransport Session and Stream Information Data Classes.

This module defines the dataclasses used by the protocol handler to store
state and information about active sessions and streams.
"""

from dataclasses import asdict, dataclass, field
from typing import Any, Dict, Optional

from ..types import Headers, SessionId, SessionState, StreamDirection, StreamId, StreamState
from ..utils import get_timestamp

__all__ = ["StreamInfo", "WebTransportSessionInfo"]


@dataclass
class StreamInfo:
    """Represents stateful information about a single WebTransport stream."""

    stream_id: StreamId
    session_id: SessionId
    direction: StreamDirection
    state: StreamState
    created_at: float
    bytes_sent: int = 0
    bytes_received: int = 0
    closed_at: Optional[float] = None
    close_code: Optional[int] = None
    close_reason: Optional[str] = None

    def __str__(self) -> str:
        """Format stream information for protocol debugging."""
        duration = ""
        if self.closed_at:
            duration = f" (duration: {self.closed_at - self.created_at:.2f}s)"
        else:
            duration = f" (active: {get_timestamp() - self.created_at:.2f}s)"
        return (
            f"Stream {self.stream_id} [{self.state.value}] "
            f"direction={self.direction.value} session={self.session_id} "
            f"sent={self.bytes_sent}b recv={self.bytes_received}b{duration}"
        )

    def to_dict(self) -> Dict[str, Any]:
        """Convert the stream information to a dictionary."""
        return asdict(self)


@dataclass
class WebTransportSessionInfo:
    """Represents stateful information about a WebTransport session."""

    session_id: SessionId
    stream_id: StreamId  # The control stream ID
    state: SessionState
    path: str
    created_at: float
    headers: Headers = field(default_factory=dict)
    ready_at: Optional[float] = None
    closed_at: Optional[float] = None
    close_code: Optional[int] = None
    close_reason: Optional[str] = None

    def __str__(self) -> str:
        """Format session information for protocol debugging."""
        duration = ""
        if self.ready_at and self.closed_at:
            duration = f" (duration: {self.closed_at - self.ready_at:.2f}s)"
        elif self.ready_at:
            duration = f" (active: {get_timestamp() - self.ready_at:.2f}s)"
        return f"Session {self.session_id} [{self.state.value}] " f"path={self.path} stream={self.stream_id}{duration}"

    def to_dict(self) -> Dict[str, Any]:
        """Convert the session information to a dictionary."""
        return asdict(self)
