from __future__ import annotations

from types import TracebackType
from typing import Literal, overload

from qroissant._config import DecodeOptions, Endpoint, PoolOptions
from qroissant._message import MessageHeader
from qroissant._values import Value

class RawResponse:
    """Read-only file-like wrapper over raw q IPC response bytes.

    Notes
    -----
    Raw queries stream responses forward-only, decoding them on demand.

    Thread Safety
    -------------
    **Not thread-safe.** Each ``RawResponse`` holds an exclusive lease on its
    parent connection — the connection cannot be reused until the response is
    fully consumed or explicitly closed.
    """

    def __enter__(self) -> RawResponse: ...
    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...
    @property
    def closed(self) -> bool:
        """Check if the response is closed."""
        ...
    @property
    def header(self) -> MessageHeader:
        """Retrieve the IPC message header."""
        ...
    def close(self) -> None:
        """Close the underlying response stream."""
        ...
    def readable(self) -> bool:
        """Return True if the stream is readable."""
        ...
    def seekable(self) -> bool:
        """Return True if the stream supports random access (returns False)."""
        ...
    def tell(self) -> int:
        """Return the current stream position."""
        ...
    def read(self, size: int | None = None, /) -> bytes:
        """Read bytes from the response payload."""
        ...
    def read1(self, size: int | None = None, /) -> bytes:
        """Read bytes from the response payload with minimal blocking."""
        ...
    def readinto(self, buffer: bytearray | memoryview, /) -> int:
        """Read payload bytes into a pre-allocated buffer."""
        ...
    def readinto1(self, buffer: bytearray | memoryview, /) -> int:
        """Read payload bytes into a pre-allocated buffer with minimal blocking."""
        ...
    def decode(self, *, options: DecodeOptions | None = None) -> Value:
        """Decode the remaining payload bytes into a qroissant value."""
        ...


class AsyncRawResponse:
    """Asynchronous read-only wrapper over raw q IPC response bytes."""

    async def __aenter__(self) -> AsyncRawResponse: ...
    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...
    @property
    def closed(self) -> bool:
        """Check if the response is closed."""
        ...
    @property
    def header(self) -> MessageHeader:
        """Retrieve the IPC message header."""
        ...
    async def close(self) -> None:
        """Close the underlying response stream."""
        ...
    async def read(self, size: int | None = None, /) -> bytes:
        """Read bytes from the response payload asynchronously."""
        ...
    async def read1(self, size: int | None = None, /) -> bytes:
        """Read bytes with minimal blocking asynchronously."""
        ...
    async def readinto(self, buffer: bytearray | memoryview, /) -> int:
        """Read payload bytes into a buffer asynchronously."""
        ...
    async def readinto1(self, buffer: bytearray | memoryview, /) -> int:
        """Read payload bytes into a buffer with minimal blocking asynchronously."""
        ...
    async def decode(self, *, options: DecodeOptions | None = None) -> Value:
        """Decode the remaining payload bytes into a qroissant value asynchronously."""
        ...


class PoolMetrics:
    """Snapshot of a pool's occupancy, configuration, and lifecycle state."""

    @property
    def connections(self) -> int:
        """Total number of currently tracked connections."""
        ...
    @property
    def idle_connections(self) -> int:
        """Number of tracked connections that are currently idle."""
        ...
    @property
    def max_size(self) -> int:
        """Configured maximum pool size."""
        ...
    @property
    def min_idle(self) -> int | None:
        """Configured minimum idle target."""
        ...
    @property
    def initialized(self) -> bool:
        """Whether the underlying pool has been created yet."""
        ...
    @property
    def closed(self) -> bool:
        """Whether the pool has been explicitly closed."""
        ...


class Connection:
    """Synchronous connection capable of executing q IPC requests.

    Parameters
    ----------
    endpoint : Endpoint
        Addressing and transport configuration.
    options : DecodeOptions | None, optional
        Default options to apply to decoded queried wrapper objects.

    Thread Safety
    -------------
    **Not thread-safe.** Use one connection per thread, or use :class:`Pool`
    for safe multi-threaded access.
    """

    def __init__(
        self,
        endpoint: Endpoint,
        *,
        options: DecodeOptions | None = None,
    ) -> None: ...
    def __enter__(self) -> Connection: ...
    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...
    def close(self) -> None:
        """Close the underlying connection."""
        ...
    @overload
    def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[False] = False,
        decode: DecodeOptions | None = None,
    ) -> Value: ...
    @overload
    def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[True],
    ) -> RawResponse: ...
    def query(
        self,
        expr: str,
        /,
        *,
        raw: bool = False,
        decode: DecodeOptions | None = None,
    ) -> Value | RawResponse:
        """Execute a synchronous q expression.

        Parameters
        ----------
        expr : str
            The q expression to evaluate remotely.
        raw : bool, default=False
            If True, returns a `RawResponse` stream instead of decoding.
        decode : DecodeOptions | None, optional
            Decoding options for this specific query, overriding connection defaults.

        Returns
        -------
        Value | RawResponse
            Decoded wrapper value or a file-like raw response if `raw=True`.
        """
        ...


class AsyncConnection:
    """Asynchronous connection capable of executing q IPC requests.

    Parameters
    ----------
    endpoint : Endpoint
        Addressing and transport configuration.
    options : DecodeOptions | None, optional
        Default options to apply to decoded queried wrapper objects.

    Thread Safety
    -------------
    **Not thread-safe.** Must be driven from a single async task. Use
    :class:`AsyncPool` for concurrent access.
    """

    def __init__(
        self,
        endpoint: Endpoint,
        *,
        options: DecodeOptions | None = None,
    ) -> None: ...
    async def __aenter__(self) -> AsyncConnection: ...
    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...
    async def close(self) -> None:
        """Close the underlying connection."""
        ...
    @overload
    async def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[False] = False,
        decode: DecodeOptions | None = None,
    ) -> Value: ...
    @overload
    async def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[True],
    ) -> AsyncRawResponse: ...
    async def query(
        self,
        expr: str,
        /,
        *,
        raw: bool = False,
        decode: DecodeOptions | None = None,
    ) -> Value | AsyncRawResponse:
        """Execute an asynchronous q expression.

        Parameters
        ----------
        expr : str
            The q expression to evaluate remotely.
        raw : bool, default=False
            If True, returns a `AsyncRawResponse` stream instead of decoding.
        decode : DecodeOptions | None, optional
            Decoding options for this specific query, overriding connection defaults.

        Returns
        -------
        Value | AsyncRawResponse
            Decoded wrapper value or a file-like raw response if `raw=True`.
        """
        ...


class Pool:
    """Synchronous connection pool for issuing q IPC requests.

    Parameters
    ----------
    endpoint : Endpoint
        Addressing and transport configuration.
    options : DecodeOptions | None, optional
        Default options to apply to decoded queried wrapper objects.
    pool : PoolOptions | None, optional
        Pool lifecycle and retry configuration.

    Thread Safety
    -------------
    **Thread-safe.** Designed for multi-threaded use — each call checks out a
    connection, uses it, and returns it to the pool automatically.
    """

    def __init__(
        self,
        endpoint: Endpoint,
        *,
        options: DecodeOptions | None = None,
        pool: PoolOptions | None = None,
    ) -> None: ...
    def __enter__(self) -> Pool: ...
    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...
    def close(self) -> None:
        """Close the pool and reject future checkouts."""
        ...
    def prewarm(self) -> PoolMetrics:
        """Create and validate idle connections ahead of the next query."""
        ...
    def metrics(self) -> PoolMetrics:
        """Return a snapshot of occupancy, configuration, and lifecycle state."""
        ...
    @overload
    def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[False] = False,
        decode: DecodeOptions | None = None,
    ) -> Value: ...
    @overload
    def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[True],
    ) -> RawResponse: ...
    def query(
        self,
        expr: str,
        /,
        *,
        raw: bool = False,
        decode: DecodeOptions | None = None,
    ) -> Value | RawResponse:
        """Execute a pooled synchronous q expression.

        Parameters
        ----------
        expr : str
            The q expression to evaluate remotely.
        raw : bool, default=False
            If True, returns a `RawResponse` stream instead of decoding.
        decode : DecodeOptions | None, optional
            Decoding options for this specific query, overriding connection defaults.

        Returns
        -------
        Value | RawResponse
            Decoded wrapper value or a file-like raw response if `raw=True`.
        """
        ...


class AsyncPool:
    """Asynchronous connection pool for issuing q IPC requests.

    Parameters
    ----------
    endpoint : Endpoint
        Addressing and transport configuration.
    options : DecodeOptions | None, optional
        Default options to apply to decoded queried wrapper objects.
    pool : PoolOptions | None, optional
        Pool lifecycle and retry configuration.

    Thread Safety
    -------------
    **Thread-safe.** Designed for concurrent use across multiple async tasks.
    """

    def __init__(
        self,
        endpoint: Endpoint,
        *,
        options: DecodeOptions | None = None,
        pool: PoolOptions | None = None,
    ) -> None: ...
    async def __aenter__(self) -> AsyncPool: ...
    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None: ...
    async def close(self) -> None:
        """Close the pool and reject future checkouts."""
        ...
    async def prewarm(self) -> PoolMetrics:
        """Create and validate idle connections ahead of the next query."""
        ...
    async def metrics(self) -> PoolMetrics:
        """Return a snapshot of occupancy, configuration, and lifecycle state."""
        ...
    @overload
    async def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[False] = False,
        decode: DecodeOptions | None = None,
    ) -> Value: ...
    @overload
    async def query(
        self,
        expr: str,
        /,
        *,
        raw: Literal[True],
    ) -> AsyncRawResponse: ...
    async def query(
        self,
        expr: str,
        /,
        *,
        raw: bool = False,
        decode: DecodeOptions | None = None,
    ) -> Value | AsyncRawResponse:
        """Execute a pooled asynchronous q expression.

        Parameters
        ----------
        expr : str
            The q expression to evaluate remotely.
        raw : bool, default=False
            If True, returns a `AsyncRawResponse` stream instead of decoding.
        decode : DecodeOptions | None, optional
            Decoding options for this specific query, overriding connection defaults.

        Returns
        -------
        Value | AsyncRawResponse
            Decoded wrapper value or a file-like raw response if `raw=True`.
        """
        ...
