from collections.abc import Callable, Iterable, Mapping, Sequence
from types import TracebackType
from typing import Any, TypeVar, overload
from typing_extensions import Literal, Self, TypeAlias

import psycopg2
import psycopg2.extensions
from psycopg2.sql import Composable

_Vars: TypeAlias = Sequence[Any] | Mapping[str, Any] | None

BINARY: Any
BINARYARRAY: Any
BOOLEAN: Any
BOOLEANARRAY: Any
BYTES: Any
BYTESARRAY: Any
CIDRARRAY: Any
DATE: Any
DATEARRAY: Any
DATETIME: Any
DATETIMEARRAY: Any
DATETIMETZ: Any
DATETIMETZARRAY: Any
DECIMAL: Any
DECIMALARRAY: Any
FLOAT: Any
FLOATARRAY: Any
INETARRAY: Any
INTEGER: Any
INTEGERARRAY: Any
INTERVAL: Any
INTERVALARRAY: Any
LONGINTEGER: Any
LONGINTEGERARRAY: Any
MACADDRARRAY: Any
NUMBER: Any
PYDATE: Any
PYDATEARRAY: Any
PYDATETIME: Any
PYDATETIMEARRAY: Any
PYDATETIMETZ: Any
PYDATETIMETZARRAY: Any
PYINTERVAL: Any
PYINTERVALARRAY: Any
PYTIME: Any
PYTIMEARRAY: Any
REPLICATION_LOGICAL: int
REPLICATION_PHYSICAL: int
ROWID: Any
ROWIDARRAY: Any
STRING: Any
STRINGARRAY: Any
TIME: Any
TIMEARRAY: Any
UNICODE: Any
UNICODEARRAY: Any
UNKNOWN: Any
adapters: dict[Any, Any]
apilevel: str
binary_types: dict[Any, Any]
encodings: dict[Any, Any]
paramstyle: str
sqlstate_errors: dict[Any, Any]
string_types: dict[Any, Any]
threadsafety: int

__libpq_version__: int

class cursor:
    arraysize: int
    binary_types: Any
    closed: Any
    connection: Any
    description: Any
    itersize: Any
    lastrowid: Any
    name: Any
    pgresult_ptr: Any
    query: Any
    row_factory: Any
    rowcount: int
    rownumber: int
    scrollable: bool | None
    statusmessage: Any
    string_types: Any
    typecaster: Any
    tzinfo_factory: Any
    withhold: bool
    def __init__(self, conn: connection, name: str | bytes | None = ...) -> None: ...
    def callproc(self, procname, parameters=...): ...
    def cast(self, oid, s): ...
    def close(self): ...
    def copy_expert(self, sql: str | bytes | Composable, file, size=...): ...
    def copy_from(self, file, table, sep=..., null=..., size=..., columns=...): ...
    def copy_to(self, file, table, sep=..., null=..., columns=...): ...
    def execute(self, query: str | bytes | Composable, vars: _Vars = ...) -> None: ...
    def executemany(self, query: str | bytes | Composable, vars_list: Iterable[_Vars]) -> None: ...
    def fetchall(self) -> list[tuple[Any, ...]]: ...
    def fetchmany(self, size: int | None = ...) -> list[tuple[Any, ...]]: ...
    def fetchone(self) -> tuple[Any, ...] | None: ...
    def mogrify(self, *args, **kwargs): ...
    def nextset(self): ...
    def scroll(self, value, mode=...): ...
    def setinputsizes(self, sizes): ...
    def setoutputsize(self, size, column=...): ...
    def __enter__(self) -> Self: ...
    def __exit__(
        self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None
    ) -> None: ...
    def __iter__(self) -> Self: ...
    def __next__(self) -> tuple[Any, ...]: ...

_Cursor: TypeAlias = cursor

class AsIs:
    adapted: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class Binary:
    adapted: Any
    buffer: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def prepare(self, conn): ...
    def __conform__(self, *args, **kwargs): ...

class Boolean:
    adapted: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class Column:
    display_size: Any
    internal_size: Any
    name: Any
    null_ok: Any
    precision: Any
    scale: Any
    table_column: Any
    table_oid: Any
    type_code: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def __eq__(self, __other): ...
    def __ge__(self, __other): ...
    def __getitem__(self, __index): ...
    def __getstate__(self): ...
    def __gt__(self, __other): ...
    def __le__(self, __other): ...
    def __len__(self) -> int: ...
    def __lt__(self, __other): ...
    def __ne__(self, __other): ...
    def __setstate__(self, state): ...

class ConnectionInfo:
    # Note: the following properties can be None if their corresponding libpq function
    # returns NULL. They're not annotated as such, because this is very unlikely in
    # practice---the psycopg2 docs [1] don't even mention this as a possibility!
    #
    # - db_name
    # - user
    # - password
    # - host
    # - port
    # - options
    #
    # (To prove this, one needs to inspect the psycopg2 source code [2], plus the
    # documentation [3] and source code [4] of the corresponding libpq calls.)
    #
    # [1]: https://www.psycopg.org/docs/extensions.html#psycopg2.extensions.ConnectionInfo
    # [2]: https://github.com/psycopg/psycopg2/blob/1d3a89a0bba621dc1cc9b32db6d241bd2da85ad1/psycopg/conninfo_type.c#L52 and below
    # [3]: https://www.postgresql.org/docs/current/libpq-status.html
    # [4]: https://github.com/postgres/postgres/blob/b39838889e76274b107935fa8e8951baf0e8b31b/src/interfaces/libpq/fe-connect.c#L6754 and below
    @property
    def backend_pid(self) -> int: ...
    @property
    def dbname(self) -> str: ...
    @property
    def dsn_parameters(self) -> dict[str, str]: ...
    @property
    def error_message(self) -> str | None: ...
    @property
    def host(self) -> str: ...
    @property
    def needs_password(self) -> bool: ...
    @property
    def options(self) -> str: ...
    @property
    def password(self) -> str: ...
    @property
    def port(self) -> int: ...
    @property
    def protocol_version(self) -> int: ...
    @property
    def server_version(self) -> int: ...
    @property
    def socket(self) -> int: ...
    @property
    def ssl_attribute_names(self) -> list[str]: ...
    @property
    def ssl_in_use(self) -> bool: ...
    @property
    def status(self) -> int: ...
    @property
    def transaction_status(self) -> int: ...
    @property
    def used_password(self) -> bool: ...
    @property
    def user(self) -> str: ...
    def __init__(self, *args, **kwargs) -> None: ...
    def parameter_status(self, name: str) -> str | None: ...
    def ssl_attribute(self, name: str) -> str | None: ...

class DataError(psycopg2.DatabaseError): ...
class DatabaseError(psycopg2.Error): ...

class Decimal:
    adapted: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class Diagnostics:
    column_name: str | None
    constraint_name: str | None
    context: str | None
    datatype_name: str | None
    internal_position: str | None
    internal_query: str | None
    message_detail: str | None
    message_hint: str | None
    message_primary: str | None
    schema_name: str | None
    severity: str | None
    severity_nonlocalized: str | None
    source_file: str | None
    source_function: str | None
    source_line: str | None
    sqlstate: str | None
    statement_position: str | None
    table_name: str | None
    def __init__(self, __err: Error) -> None: ...

class Error(Exception):
    cursor: _Cursor | None
    diag: Diagnostics
    pgcode: str | None
    pgerror: str | None
    def __init__(self, *args, **kwargs) -> None: ...
    def __reduce__(self): ...
    def __setstate__(self, state): ...

class Float:
    adapted: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class ISQLQuote:
    _wrapped: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getbinary(self, *args, **kwargs): ...
    def getbuffer(self, *args, **kwargs): ...
    def getquoted(self, *args, **kwargs): ...

class Int:
    adapted: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class IntegrityError(psycopg2.DatabaseError): ...
class InterfaceError(psycopg2.Error): ...
class InternalError(psycopg2.DatabaseError): ...

class List:
    adapted: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def prepare(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class NotSupportedError(psycopg2.DatabaseError): ...

class Notify:
    channel: Any
    payload: Any
    pid: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def __eq__(self, __other): ...
    def __ge__(self, __other): ...
    def __getitem__(self, __index): ...
    def __gt__(self, __other): ...
    def __hash__(self) -> int: ...
    def __le__(self, __other): ...
    def __len__(self) -> int: ...
    def __lt__(self, __other): ...
    def __ne__(self, __other): ...

class OperationalError(psycopg2.DatabaseError): ...
class ProgrammingError(psycopg2.DatabaseError): ...
class QueryCanceledError(psycopg2.OperationalError): ...

class QuotedString:
    adapted: Any
    buffer: Any
    encoding: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def getquoted(self, *args, **kwargs): ...
    def prepare(self, *args, **kwargs): ...
    def __conform__(self, *args, **kwargs): ...

class ReplicationConnection(psycopg2.extensions.connection):
    autocommit: Any
    isolation_level: Any
    replication_type: Any
    reset: Any
    set_isolation_level: Any
    set_session: Any
    def __init__(self, *args, **kwargs) -> None: ...

class ReplicationCursor(cursor):
    feedback_timestamp: Any
    io_timestamp: Any
    wal_end: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def consume_stream(self, consumer, keepalive_interval=...): ...
    def read_message(self, *args, **kwargs): ...
    def send_feedback(self, write_lsn=..., flush_lsn=..., apply_lsn=..., reply=..., force=...): ...
    def start_replication_expert(self, command, decode=..., status_interval=...): ...

class ReplicationMessage:
    cursor: Any
    data_size: Any
    data_start: Any
    payload: Any
    send_time: Any
    wal_end: Any
    def __init__(self, *args, **kwargs) -> None: ...

class TransactionRollbackError(psycopg2.OperationalError): ...
class Warning(Exception): ...

class Xid:
    bqual: Any
    database: Any
    format_id: Any
    gtrid: Any
    owner: Any
    prepared: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def from_string(self, *args, **kwargs): ...
    def __getitem__(self, __index): ...
    def __len__(self) -> int: ...

_T_cur = TypeVar("_T_cur", bound=cursor)

class connection:
    DataError: Any
    DatabaseError: Any
    Error: Any
    IntegrityError: Any
    InterfaceError: Any
    InternalError: Any
    NotSupportedError: Any
    OperationalError: Any
    ProgrammingError: Any
    Warning: Any
    @property
    def async_(self) -> int: ...
    autocommit: bool
    @property
    def binary_types(self) -> Any: ...
    @property
    def closed(self) -> int: ...
    cursor_factory: Callable[..., _Cursor]
    @property
    def dsn(self) -> str: ...
    @property
    def encoding(self) -> str: ...
    @property
    def info(self) -> ConnectionInfo: ...
    @property
    def isolation_level(self) -> int | None: ...
    @isolation_level.setter
    def isolation_level(self, __value: str | bytes | int | None) -> None: ...
    notices: list[Any]
    notifies: list[Any]
    @property
    def pgconn_ptr(self) -> int | None: ...
    @property
    def protocol_version(self) -> int: ...
    @property
    def deferrable(self) -> bool | None: ...
    @deferrable.setter
    def deferrable(self, __value: Literal["default"] | bool | None) -> None: ...
    @property
    def readonly(self) -> bool | None: ...
    @readonly.setter
    def readonly(self, __value: Literal["default"] | bool | None) -> None: ...
    @property
    def server_version(self) -> int: ...
    @property
    def status(self) -> int: ...
    @property
    def string_types(self) -> Any: ...
    # Really it's dsn: str, async: int = ..., async_: int = ..., but
    # that would be a syntax error.
    def __init__(self, dsn: str, *, async_: int = ...) -> None: ...
    def cancel(self) -> None: ...
    def close(self) -> None: ...
    def commit(self) -> None: ...
    @overload
    def cursor(self, name: str | bytes | None = ..., *, withhold: bool = ..., scrollable: bool | None = ...) -> _Cursor: ...
    @overload
    def cursor(
        self,
        name: str | bytes | None = ...,
        *,
        cursor_factory: Callable[..., _T_cur],
        withhold: bool = ...,
        scrollable: bool | None = ...,
    ) -> _T_cur: ...
    @overload
    def cursor(
        self, name: str | bytes | None, cursor_factory: Callable[..., _T_cur], withhold: bool = ..., scrollable: bool | None = ...
    ) -> _T_cur: ...
    def fileno(self) -> int: ...
    def get_backend_pid(self) -> int: ...
    def get_dsn_parameters(self) -> dict[str, str]: ...
    def get_native_connection(self): ...
    def get_parameter_status(self, parameter: str) -> str | None: ...
    def get_transaction_status(self) -> int: ...
    def isexecuting(self) -> bool: ...
    def lobject(
        self,
        oid: int = ...,
        mode: str | None = ...,
        new_oid: int = ...,
        new_file: str | None = ...,
        lobject_factory: type[lobject] = ...,
    ) -> lobject: ...
    def poll(self) -> int: ...
    def reset(self) -> None: ...
    def rollback(self) -> None: ...
    def set_client_encoding(self, encoding: str) -> None: ...
    def set_isolation_level(self, level: int | None) -> None: ...
    def set_session(
        self,
        isolation_level: str | bytes | int | None = ...,
        readonly: bool | Literal["default", b"default"] | None = ...,
        deferrable: bool | Literal["default", b"default"] | None = ...,
        autocommit: bool = ...,
    ) -> None: ...
    def tpc_begin(self, xid: str | bytes | Xid) -> None: ...
    def tpc_commit(self, __xid: str | bytes | Xid = ...) -> None: ...
    def tpc_prepare(self) -> None: ...
    def tpc_recover(self) -> list[Xid]: ...
    def tpc_rollback(self, __xid: str | bytes | Xid = ...) -> None: ...
    def xid(self, format_id, gtrid, bqual) -> Xid: ...
    def __enter__(self) -> Self: ...
    def __exit__(self, __type: object, __name: object, __tb: object) -> None: ...

class lobject:
    closed: Any
    mode: Any
    oid: Any
    def __init__(self, *args, **kwargs) -> None: ...
    def close(self): ...
    def export(self, filename): ...
    def read(self, size=...): ...
    def seek(self, offset, whence=...): ...
    def tell(self): ...
    def truncate(self, len=...): ...
    def unlink(self): ...
    def write(self, str): ...

def Date(year, month, day): ...
def DateFromPy(*args, **kwargs): ...
def DateFromTicks(ticks): ...
def IntervalFromPy(*args, **kwargs): ...
def Time(hour, minutes, seconds, tzinfo=...): ...
def TimeFromPy(*args, **kwargs): ...
def TimeFromTicks(ticks): ...
def Timestamp(year, month, day, hour, minutes, seconds, tzinfo=...): ...
def TimestampFromPy(*args, **kwargs): ...
def TimestampFromTicks(ticks): ...
def _connect(*args, **kwargs): ...
def adapt(*args, **kwargs): ...
def encrypt_password(*args, **kwargs): ...
def get_wait_callback(*args, **kwargs): ...
def libpq_version(*args, **kwargs): ...
def new_array_type(oids, name, baseobj): ...
def new_type(oids, name, castobj): ...
def parse_dsn(dsn: str | bytes) -> dict[str, Any]: ...
def quote_ident(*args, **kwargs): ...
def register_type(*args, **kwargs): ...
def set_wait_callback(_none): ...
