from collections.abc import Callable, Iterable, Iterator, Sequence
from datetime import datetime, timedelta
from decimal import Decimal
from typing import Any
from typing_extensions import Self

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

_OutputField = Field[Any, Any] | str

class SQLiteNumericMixin:
    def as_sqlite(
        self, compiler: SQLCompiler, connection: Any, **extra_context: Any
    ) -> tuple[str, list[float]]: ...

_Numeric = 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) -> Self: ...
    def bitand(self, other: int) -> Self: ...
    def bitleftshift(self, other: int) -> Self: ...
    def bitrightshift(self, other: int) -> Self: ...
    def __or__(self, other: Combinable) -> 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
    ) -> 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): ...
