from collections.abc import Iterable, Iterator
from typing import Any, Generic, TypeVar

from psycopg2._psycopg import connection, cursor

_T = TypeVar("_T")

class Composable:
    def __init__(self, wrapped: Any) -> None: ...
    def as_string(self, context: connection | cursor) -> str: ...
    def __add__(self, other: Composable) -> Composed: ...
    def __mul__(self, n: int) -> Composed: ...
    def __eq__(self, other: object) -> bool: ...
    def __ne__(self, other: object) -> bool: ...

class Composed(Composable):
    def __init__(self, seq: Iterable[Composable]) -> None: ...
    @property
    def seq(self) -> list[Composable]: ...
    def __iter__(self) -> Iterator[Composable]: ...
    def __add__(self, other: Composable) -> Composed: ...
    def join(self, joiner: str | SQL) -> Composed: ...

class SQL(Composable):
    def __init__(self, string: str) -> None: ...
    @property
    def string(self) -> str: ...
    def format(self, *args: Composable, **kwargs: Composable) -> Composed: ...
    def join(self, seq: Iterable[Composable]) -> Composed: ...

class Identifier(Composable):
    def __init__(self, *strings: str) -> None: ...
    @property
    def strings(self) -> tuple[str, ...]: ...
    @property
    def string(self) -> str: ...

class Literal(Composable, Generic[_T]):
    def __init__(self, wrapped: _T) -> None: ...
    @property
    def wrapped(self) -> _T: ...

class Placeholder(Composable):
    def __init__(self, name: str | None = None) -> None: ...
    @property
    def name(self) -> str | None: ...

NULL: SQL
DEFAULT: SQL
