from collections.abc import Generator, Sequence
from typing import Any

from django.core import checks
from django.db import models
from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.models import Field
from django.db.models.expressions import Expression
from django.db.models.lookups import Lookup, Transform
from django.forms import Field as FormField
from django.utils.functional import cached_property
from wagtail.blocks import Block, BlockField, StreamBlock, StreamValue
from wagtail.blocks.base import BoundBlock

class RichTextField(models.TextField[str, str]):
    editor: str
    features: list[str] | None
    def __init__(
        self, *args: Any, editor: str = "default", features: list[str] | None = None, **kwargs: Any
    ) -> None: ...
    def clone(self) -> RichTextField: ...
    def formfield(self, **kwargs: Any) -> FormField: ...
    def get_searchable_content(self, value: str) -> list[str]: ...
    def extract_references(self, value: str) -> Generator[tuple[str, str, str, str]]: ...

class Creator:
    field: Field[Any, Any]
    def __init__(self, field: Field[Any, Any]) -> None: ...
    def __get__(self, obj: models.Model | None, type: type | None = None) -> StreamValue: ...
    def __set__(self, obj: models.Model, value: StreamValue | list[Any] | str | None) -> None: ...

class StreamField(models.Field[StreamValue, StreamValue]):
    block_opts: dict[str, Any]
    block_types_arg: type[StreamBlock] | StreamBlock | Sequence[tuple[str, Block]]
    block_lookup: dict[str, Any] | None
    def __init__(
        self,
        block_types: type[StreamBlock] | StreamBlock | Sequence[tuple[str, Block]],
        use_json_field: bool = True,
        block_lookup: dict[str, Any] | None = None,
        *,
        min_num: int | None = ...,
        max_num: int | None = ...,
        block_counts: dict[str, dict[str, int]] | None = ...,
        collapsed: bool = ...,
        **kwargs: Any,
    ) -> None: ...
    @cached_property
    def stream_block(self) -> StreamBlock: ...
    @property
    def json_field(self) -> models.JSONField[Any, Any]: ...
    def get_internal_type(self) -> str: ...
    def get_lookup(self, lookup_name: str) -> type[Lookup[Any]] | None: ...
    def get_transform(self, lookup_name: str) -> type[Transform[Any]] | None: ...
    def deconstruct(self) -> tuple[str, str, list[Any], dict[str, Any]]: ...
    def to_python(self, value: str | list[Any] | StreamValue | None) -> StreamValue: ...
    def get_prep_value(self, value: StreamValue | None) -> str | None: ...
    def get_db_prep_value(
        self, value: str | None, connection: BaseDatabaseWrapper, prepared: bool = False
    ) -> str | None: ...
    def from_db_value(
        self, value: str | None, expression: Expression, connection: BaseDatabaseWrapper
    ) -> StreamValue: ...
    def formfield(self, **kwargs: Any) -> BlockField: ...
    def get_default(self) -> StreamValue: ...
    def value_to_string(self, obj: models.Model) -> str: ...
    def get_searchable_content(self, value: StreamValue) -> list[str]: ...
    def extract_references(self, value: StreamValue) -> Generator[tuple[str, str, str, str]]: ...
    def get_block_by_content_path(self, value: StreamValue, path_elements: list[str]) -> BoundBlock | None: ...
    def check(self, **kwargs: Any) -> list[checks.Error]: ...
    def contribute_to_class(self, cls: type[models.Model], name: str, **kwargs: Any) -> None: ...
