from typing import Any, Callable, ContextManager, Mapping, Optional, TypeVar, Union

from bson.timestamp import Timestamp
from pymongo.mongo_client import MongoClient
from pymongo.read_concern import ReadConcern
from pymongo.read_preferences import _ServerMode
from pymongo.write_concern import WriteConcern

class SessionOptions:
    def __init__(
        self,
        causal_consistency: Optional[bool] = ...,
        default_transaction_options: Optional[TransactionOptions] = ...,
        snapshot: Optional[bool] = ...,
    ) -> None: ...
    @property
    def causal_consistency(self) -> bool: ...
    @property
    def default_transaction_options(self) -> Optional[TransactionOptions]: ...

class TransactionOptions:
    def __init__(
        self,
        read_concern: Optional[ReadConcern] = ...,
        write_concern: Optional[WriteConcern] = ...,
        read_preference: Optional[_ServerMode] = ...,
        max_commit_time_ms: Optional[int] = ...,
    ) -> None: ...
    @property
    def read_concern(self) -> Optional[ReadConcern]: ...
    @property
    def write_concern(self) -> Optional[WriteConcern]: ...
    @property
    def read_preference(self) -> Optional[_ServerMode]: ...
    @property
    def max_commit_time_ms(self) -> Optional[int]: ...

_T = TypeVar("_T")

class ClientSession:
    def __init__(
        self, client: MongoClient, server_session: Any, options: SessionOptions, authset: Any, implicit: bool
    ) -> None: ...
    def end_session(self) -> None: ...
    def __enter__(self) -> ClientSession: ...
    def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: ...
    @property
    def client(self) -> MongoClient: ...
    @property
    def options(self) -> SessionOptions: ...
    @property
    def session_id(self) -> Mapping[str, Any]: ...
    @property
    def cluster_time(self) -> Optional[Mapping[str, Any]]: ...
    @property
    def operation_time(self) -> Optional[Timestamp]: ...
    def with_transaction(
        self,
        callback: Callable[[ClientSession], _T],
        read_concern: Optional[ReadConcern] = ...,
        write_concern: Optional[WriteConcern] = ...,
        read_preference: Optional[_ServerMode] = ...,
        max_commit_time_ms: Optional[int] = ...,
    ) -> _T: ...
    def start_transaction(
        self,
        read_concern: Optional[ReadConcern] = ...,
        write_concern: Optional[WriteConcern] = ...,
        read_preference: Optional[_ServerMode] = ...,
        max_commit_time_ms: Optional[int] = ...,
    ) -> ContextManager: ...
    def commit_transaction(self) -> None: ...
    def abort_transaction(self) -> None: ...
    def advance_cluster_time(self, cluster_time: Mapping[str, Any]) -> None: ...
    def advance_operation_time(self, operation_time: Timestamp) -> None: ...
    @property
    def has_ended(self) -> bool: ...
    @property
    def in_transaction(self) -> bool: ...
    def __copy__(self) -> None: ...
