from types import TracebackType
from typing import (
    Any,
    Iterable,
    Iterator,
    Literal,
    Mapping,
    Self,
    TypeAlias,
    final,
)


_InputData: TypeAlias = str | int | float | None
_AdaptedInputData: TypeAlias = _InputData | Any
_Parameters: TypeAlias = Mapping[str, _AdaptedInputData]


@final
class _Statement: ...


class Cursor(Iterator[Any]):
    arraysize: int
    @property
    def description(self) -> tuple[tuple[str, None, None, None, None, None, None], ...] | Any: ...
    @property
    def lastrowid(self) -> int | None: ...
    @property
    def rowcount(self) -> int: ...
    def close(self) -> None: ...
    def execute(self, sql: str, parameters: _Parameters = (), /) -> Self: ...
    def executemany(self, sql: str, seq_of_parameters: Iterable[_Parameters], /) -> Self: ...
    def executescript(self, sql_script: str, /) -> Self: ...
    def fetchall(self) -> list[Any]: ...
    def fetchmany(self, size: int | None = 1) -> list[Any]: ...
    def fetchone(self) -> Any: ...
    def __iter__(self) -> Self: ...
    def __next__(self) -> Any: ...


class Connection:
    def close(self) -> None: ...
    def commit(self) -> None: ...
    def cursor(self, factory: None = None) -> Cursor: ...
    def execute(self, sql: str, parameters: _Parameters = ..., /) -> Cursor: ...
    def executemany(self, sql: str, parameters: Iterable[_Parameters], /) -> Cursor: ...
    def executescript(self, sql_script: str, /) -> Cursor: ...
    def rollback(self) -> None: ...

    def __call__(self, sql: str, /) -> _Statement: ...
    def __enter__(self) -> Self: ...
    def __exit__(
        self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None, /
    ) -> Literal[False]: ...


class ConnectionPool:
    # SQLAlchemy (whole engine is passed)
    def connect(self) -> Connection: ...
    # mysql-connector-python
    def get_connection(self) -> Connection: ...
    # psycopg2
    def getconn(self) -> Connection: ...
    def putconn(self, connection: Connection, /) -> None: ...
    # Common
    def close(self) -> None: ...
