from collections.abc import Iterator
from typing import Any

from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.models.expressions import Expression, Func
from django.db.models.fields import Field
from django.db.models.lookups import Exact, GreaterThan, GreaterThanOrEqual, In, IsNull, LessThan, LessThanOrEqual
from django.db.models.sql.compiler import SQLCompiler, _AsSqlType
from typing_extensions import override

class Tuple(Func):
    function: str
    output_field: Field
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[Expression]: ...
    @override
    def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ...  # type: ignore[override]

class TupleLookupMixin:
    allows_composite_expressions: bool
    def get_prep_lookup(self) -> Any: ...
    def check_rhs_is_tuple_or_list(self) -> None: ...
    def check_rhs_length_equals_lhs_length(self) -> None: ...
    def check_rhs_is_supported_expression(self) -> None: ...
    def get_lhs_str(self) -> str: ...
    def get_prep_lhs(self) -> Any: ...
    def process_lhs(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, lhs: Any = None) -> _AsSqlType: ...
    def process_rhs(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ...
    def get_fallback_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ...
    def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ...

class TupleExact(TupleLookupMixin, Exact): ...
class TupleIsNull(TupleLookupMixin, IsNull): ...
class TupleGreaterThan(TupleLookupMixin, GreaterThan): ...
class TupleGreaterThanOrEqual(TupleLookupMixin, GreaterThanOrEqual): ...
class TupleLessThan(TupleLookupMixin, LessThan): ...
class TupleLessThanOrEqual(TupleLookupMixin, LessThanOrEqual): ...

class TupleIn(TupleLookupMixin, In):
    def check_rhs_is_collection_of_tuples_or_lists(self) -> None: ...
    def check_rhs_elements_length_equals_lhs_length(self) -> None: ...
    def check_rhs_is_query(self) -> None: ...

tuple_lookups: dict[str, type[TupleLookupMixin]]
