from collections.abc import Callable, Iterable, Iterator, Sequence
from datetime import datetime, timedelta
from decimal import Decimal
from typing import Any, TypeAlias

from django.db.models import Q, QuerySet
from django.db.models.fields import Field
from django.db.models.lookups import Lookup
from django.db.models.query import _BaseQuerySet
from django.db.models.sql.compiler import SQLCompiler
from typing_extensions import Self

_OutputField: TypeAlias = Field[Any, Any] | str

class SQLiteNumericMixin:
    def as_sqlite(
        self, compiler: SQLCompiler, connection: Any, **extra_context: Any
    ) -> tuple[str, list[float]]: ...

_Numeric: TypeAlias = float | Decimal

class Combinable:
    ADD: str = ...
    SUB: str = ...
    MUL: str = ...
    DIV: str = ...
    POW: str = ...
    MOD: str = ...
    BITAND: str = ...
    BITOR: str = ...
    BITLEFTSHIFT: str = ...
    BITRIGHTSHIFT: str = ...
    def __neg__(self) -> Self: ...
    def __add__(
        self, other: timedelta | Combinable | _Numeric | str | None
    ) -> Self: ...
    def __sub__(self, other: timedelta | Combinable | _Numeric) -> Self: ...
    def __mul__(self, other: timedelta | Combinable | _Numeric) -> Self: ...
    def __truediv__(self, other: Combinable | _Numeric) -> Self: ...
    def __itruediv__(self, other: Combinable | _Numeric) -> Self: ...
    def __mod__(self, other: int | Combinable) -> Self: ...
    def __pow__(self, other: _Numeric | Combinable) -> Self: ...
    def __and__(self, other: Combinable | Q) -> Self: ...
    def bitand(self, other: int) -> Self: ...
    def bitleftshift(self, other: int) -> Self: ...
    def bitrightshift(self, other: int) -> Self: ...
    def __or__(self, other: Combinable | Q) -> Self: ...
    def bitor(self, other: int) -> Self: ...
    def __radd__(
        self, other: datetime | _Numeric | Combinable | None
    ) -> Combinable: ...
    def __rsub__(self, other: datetime | _Numeric | Combinable) -> Combinable: ...
    def __rmul__(self, other: _Numeric | Combinable) -> Combinable: ...
    def __rtruediv__(self, other: _Numeric | Combinable) -> Combinable: ...
    def __rmod__(self, other: int | Combinable) -> Combinable: ...
    def __rpow__(self, other: _Numeric | Combinable) -> Combinable: ...
    def __rand__(self, other: Any) -> Combinable: ...
    def __ror__(self, other: Any) -> Combinable: ...

class BaseExpression:
    is_summary: bool = ...
    filterable: bool = ...
    window_compatible: bool = ...
    def __init__(self, output_field: _OutputField | None = ...) -> None: ...
    def get_db_converters(self, connection: Any) -> list[Callable[..., Any]]: ...
    def get_source_expressions(self) -> list[Any]: ...
    def set_source_expressions(self, exprs: Sequence[Combinable]) -> None: ...
    @property
    def contains_aggregate(self) -> bool: ...
    @property
    def contains_over_clause(self) -> bool: ...
    @property
    def contains_column_references(self) -> bool: ...
    def resolve_expression(
        self,
        query: Any = ...,
        allow_joins: bool = ...,
        reuse: set[str] | None = ...,
        summarize: bool = ...,
        for_save: bool = ...,
    ) -> Self: ...
    @property
    def field(self) -> Field[Any, Any]: ...
    @property
    def output_field(self) -> Field[Any, Any]: ...
    @property
    def convert_value(self) -> Callable[..., Any]: ...
    def get_lookup(self, lookup: str) -> type[Lookup[Any]] | None: ...
    def get_transform(self, name: str) -> type[Expression] | None: ...
    def relabeled_clone(self, change_map: dict[str | None, str]) -> Expression: ...
    def copy(self) -> BaseExpression: ...
    def get_group_by_cols(self) -> list[Self]: ...
    def get_source_fields(self) -> list[Field[Any, Any] | None]: ...
    def asc(self, **kwargs: Any) -> Expression: ...
    def desc(self, **kwargs: Any) -> Expression: ...
    def reverse_ordering(self) -> Any: ...
    def flatten(self) -> Iterator[Expression]: ...
    def deconstruct(self) -> Any: ...
    def as_sqlite(self, compiler: SQLCompiler, connection: Any) -> Any: ...
    def as_sql(
        self, compiler: SQLCompiler, connection: Any, **extra_context: Any
    ) -> tuple[str, list[Any] | tuple[Any]]: ...
    def as_mysql(self, compiler: Any, connection: Any) -> Any: ...
    def as_postgresql(self, compiler: Any, connection: Any) -> Any: ...
    def as_oracle(self, compiler: Any, connection: Any) -> Any: ...

class Expression(BaseExpression, Combinable): ...

class CombinedExpression(SQLiteNumericMixin, Expression):
    connector: Any = ...
    lhs: Any = ...
    rhs: Any = ...
    def __init__(
        self,
        lhs: Combinable,
        connector: str,
        rhs: Combinable,
        output_field: _OutputField | None = ...,
    ) -> None: ...

class F(Combinable):
    name: str
    def __init__(self, name: str) -> None: ...
    def resolve_expression(
        self,
        query: Any = ...,
        allow_joins: bool = ...,
        reuse: set[str] | None = ...,
        summarize: bool = ...,
        for_save: bool = ...,
    ) -> Self: ...
    def asc(self, **kwargs: Any) -> OrderBy: ...
    def desc(self, **kwargs: Any) -> OrderBy: ...
    def deconstruct(self) -> Any: ...

class OuterRef(F):
    def __init__(self, name: str | OuterRef) -> None: ...

class Subquery(Expression):
    template: str = ...
    queryset: QuerySet[Any] = ...
    extra: dict[Any, Any] = ...
    def __init__(
        self,
        queryset: _BaseQuerySet[Any],
        output_field: _OutputField | None = ...,
        **extra: Any
    ) -> None: ...

class Exists(Subquery):
    negated: bool = ...
    def __init__(self, *args: Any, negated: bool = ..., **kwargs: Any) -> None: ...
    def __invert__(self) -> Exists: ...

class OrderBy(BaseExpression):
    template: str = ...
    nulls_first: bool = ...
    nulls_last: bool = ...
    descending: bool = ...
    expression: Expression = ...
    def __init__(
        self,
        expression: Combinable,
        descending: bool = ...,
        nulls_first: bool = ...,
        nulls_last: bool = ...,
    ) -> None: ...

class Value(Expression):
    value: Any = ...
    def __init__(self, value: Any, output_field: _OutputField | None = ...) -> None: ...

class RawSQL(Expression):
    params: list[Any]
    sql: str
    def __init__(
        self,
        sql: str,
        params: Sequence[Any],
        output_field: _OutputField | None = ...,
    ) -> None: ...

class Func(SQLiteNumericMixin, Expression):
    function: str = ...
    name: str = ...
    template: str = ...
    arg_joiner: str = ...
    arity: int = ...
    source_expressions: list[Combinable] = ...
    extra: dict[Any, Any] = ...
    def __init__(
        self, *expressions: Any, output_field: _OutputField | None = ..., **extra: Any
    ) -> None: ...

class When(Expression):
    template: str = ...
    condition: Any = ...
    result: Any = ...
    def __init__(
        self, condition: Any = ..., then: Any = ..., **lookups: Any
    ) -> None: ...

class Case(Expression):
    template: str = ...
    case_joiner: str = ...
    cases: Any = ...
    default: Any = ...
    extra: Any = ...
    def __init__(
        self,
        *cases: Any,
        default: Any | None = ...,
        output_field: _OutputField | None = ...,
        **extra: Any
    ) -> None: ...

class ExpressionWrapper(Expression):
    def __init__(
        self, expression: Q | Combinable, output_field: _OutputField
    ) -> None: ...

class Col(Expression):
    def __init__(
        self, alias: str, target: str, output_field: _OutputField | None = ...
    ) -> None: ...

class SimpleCol(Expression):
    contains_column_references: bool = ...
    def __init__(
        self, target: Field[Any, Any], output_field: _OutputField | None = ...
    ) -> None: ...

class Ref(Expression):
    def __init__(self, refs: str, source: Expression) -> None: ...

class ExpressionList(Func):
    def __init__(
        self, *expressions: BaseExpression | Combinable, **extra: Any
    ) -> None: ...

class Random(Expression): ...

class Window(Expression):
    template: str = ...
    contains_aggregate: bool = ...
    contains_over_clause: bool = ...
    def __init__(
        self,
        expression: BaseExpression,
        partition_by: (
            str | Iterable[BaseExpression | F] | F | BaseExpression | None
        ) = ...,
        order_by: Sequence[BaseExpression | F] | BaseExpression | F | None = ...,
        frame: WindowFrame | None = ...,
        output_field: _OutputField | None = ...,
    ) -> None: ...

class WindowFrame(Expression):
    template: str = ...
    frame_type: str = ...
    def __init__(self, start: int | None = ..., end: int | None = ...) -> None: ...
    def window_frame_start_end(
        self, connection: Any, start: int | None, end: int | None
    ) -> tuple[int, int]: ...

class RowRange(WindowFrame): ...
class ValueRange(WindowFrame): ...
