from typing import Any, ClassVar

from django.db import models
from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.models import Func, Transform
from django.db.models.expressions import Combinable, Expression, Value, _OutputField
from django.db.models.sql.compiler import SQLCompiler, _AsSqlType
from typing_extensions import override

class MySQLSHA2Mixin:
    def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class OracleHashMixin:
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class PostgreSQLSHAMixin:
    def as_postgresql(
        self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any
    ) -> _AsSqlType: ...

class Chr(Transform):
    def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class ConcatPair(Func):
    def pipes_concat_sql(
        self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any
    ) -> _AsSqlType: ...
    def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...  # type: ignore[override]
    def as_postgresql(
        self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any
    ) -> _AsSqlType: ...
    def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...
    def coalesce(self) -> ConcatPair: ...

class Concat(Func):
    def __init__(self, *expressions: Any, **extra: Any) -> None: ...

class Left(Func):
    output_field: ClassVar[models.CharField[Any]]
    def __init__(
        self,
        expression: Combinable | str,
        length: Expression | int,
        *,
        output_field: _OutputField | None = None,
        **extra: Any,
    ) -> None: ...
    def get_substr(self) -> Substr: ...
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class Length(Transform):
    output_field: ClassVar[models.IntegerField[Any]]
    def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class Lower(Transform): ...

class LPad(Func):
    output_field: ClassVar[models.CharField[Any]]
    def __init__(
        self, expression: Combinable | str, length: Expression | int | None, fill_text: Expression = ..., **extra: Any
    ) -> None: ...

class LTrim(Transform): ...
class MD5(OracleHashMixin, Transform): ...

class Ord(Transform):
    output_field: ClassVar[models.IntegerField[Any]]
    def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class Repeat(Func):
    output_field: ClassVar[models.CharField[Any]]
    def __init__(self, expression: Combinable | str, number: Expression | int | None, **extra: Any) -> None: ...
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class Replace(Func):
    def __init__(self, expression: Combinable | str, text: Value, replacement: Value = ..., **extra: Any) -> None: ...

class Reverse(Transform):
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class Right(Left):
    @override
    def get_substr(self) -> Substr: ...

class RPad(LPad): ...
class RTrim(Transform): ...
class SHA1(OracleHashMixin, PostgreSQLSHAMixin, Transform): ...

class SHA224(MySQLSHA2Mixin, PostgreSQLSHAMixin, Transform):
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class SHA256(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ...
class SHA384(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ...
class SHA512(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ...

class StrIndex(Func):
    output_field: ClassVar[models.IntegerField[Any]]
    def as_postgresql(
        self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any
    ) -> _AsSqlType: ...

class Substr(Func):
    output_field: ClassVar[models.CharField[Any]]
    def __init__(
        self,
        expression: Combinable | str,
        pos: Expression | int,
        length: Expression | int | None = None,
        *,
        output_field: _OutputField | None = None,
        **extra: Any,
    ) -> None: ...
    def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ...

class Trim(Transform): ...
class Upper(Transform): ...
