from collections.abc import Callable, Mapping
from typing import Any, Protocol, TypeAlias, TypedDict

from curl_cffi import CurlMime

BodyData = bytes | Mapping[str, Any]
ContentCallback: TypeAlias = Callable[[bytes], int]


class _Resp(Protocol):
    """Minimal interface for an HTTP response object."""

    status_code: int
    content: bytes
    headers: Mapping[str, str] | None = None


class SyncSession(Protocol):
    """Structural type for a synchronous HTTP session (e.g. ``curl_cffi.Session``)."""

    def request(
        self,
        method: str,
        url: str,
        *,
        headers: Mapping[str, str],
        params: Mapping[str, Any] | None,
        data: BodyData | None,
        json: dict[str, Any] | None,
        timeout: float | tuple[float, float],
        stream: bool = False,
        multipart: CurlMime | None = None,
        content_callback: ContentCallback | None = None,
    ) -> _Resp: ...
    def close(self) -> None: ...


class AsyncSession(Protocol):
    """Structural type for an asynchronous HTTP session (e.g. ``curl_cffi.AsyncSession``)."""

    async def request(
        self,
        method: str,
        url: str,
        *,
        headers: Mapping[str, str],
        params: Mapping[str, Any] | None,
        data: BodyData | None,
        json: dict[str, Any] | None,
        timeout: float | tuple[float, float],
        stream: bool = False,
        multipart: CurlMime | None = None,
    ) -> _Resp: ...
    async def close(self) -> None: ...


class RequestKwargs(TypedDict, total=False):
    params: Mapping[str, Any] | None
    headers: Mapping[str, str] | None
    json: dict[str, Any] | None
    data: BodyData | None
    stream: bool
    multipart: CurlMime | None
