from typing import Any, Iterable, List, Mapping, Optional, Union

from bson.errors import (
    InvalidBSON as InvalidBSON,
    InvalidDocument as InvalidDocument,
    InvalidId as InvalidId,
    InvalidStringData as InvalidStringData,
)

class CertificateError(ValueError): ...

class PyMongoError(Exception):
    def __init__(self, message: str = ..., error_labels: Optional[Iterable[str]] = ...) -> None: ...
    def has_error_label(self, label: str) -> bool: ...

class ProtocolError(PyMongoError): ...
class ConnectionFailure(PyMongoError): ...

class AutoReconnect(ConnectionFailure):
    # TODO: remove List[Any] in pymongo 4.0
    errors: Union[Mapping[str, Any], List[Any]] = ...
    details: Union[Mapping[str, Any], List[Any]] = ...
    def __init__(self, message: str = ..., errors: Optional[Union[Mapping[str, Any], List[Any]]] = ...) -> None: ...

class NetworkTimeout(AutoReconnect): ...
class NotMasterError(AutoReconnect): ...
class ServerSelectionTimeoutError(AutoReconnect): ...
class ConfigurationError(PyMongoError): ...

class OperationFailure(PyMongoError):
    def __init__(
        self,
        error: str,
        code: Optional[int] = ...,
        details: Optional[Mapping[str, Any]] = ...,
        max_wire_version: Optional[int] = ...,
    ) -> None: ...
    @property
    def code(self) -> Optional[int]: ...
    @property
    def details(self) -> Optional[Mapping[str, Any]]: ...

class CursorNotFound(OperationFailure): ...
class ExecutionTimeout(OperationFailure): ...
class WriteConcernError(OperationFailure): ...
class WriteError(OperationFailure): ...
class WTimeoutError(WriteConcernError): ...
class DuplicateKeyError(WriteError): ...

class BulkWriteError(OperationFailure):
    def __init__(self, results: Mapping[str, Any]) -> None: ...

class InvalidOperation(PyMongoError): ...
class InvalidName(PyMongoError): ...
class CollectionInvalid(PyMongoError): ...
class InvalidURI(ConfigurationError): ...
class ExceededMaxWaiters(PyMongoError): ...
class DocumentTooLarge(InvalidDocument): ...

class EncryptionError(PyMongoError):
    def __init__(self, cause: Exception) -> None: ...
    @property
    def cause(self): ...
