from collections.abc import Iterable
from typing import Any

from django.contrib.postgres.search import SearchVector
from django.db import models
from django.db.models import QuerySet
from wagtail.search.backends.base import BaseSearchBackend, BaseSearchQueryCompiler, BaseSearchResults
from wagtail.search.index import AutocompleteField, BaseField, SearchField

class ObjectIndexer:
    obj: models.Model
    backend: PostgresSearchBackend
    def __init__(self, obj: models.Model, backend: PostgresSearchBackend) -> None: ...
    def prepare_value(self, value: Any) -> str: ...
    def prepare_field(self, obj: models.Model, field: BaseField) -> list[tuple[str, str, str]]: ...
    @property
    def id(self) -> str: ...
    @property
    def title(self) -> str: ...
    @property
    def body(self) -> str: ...
    @property
    def autocomplete(self) -> str: ...
    def as_vector(self, texts: list[tuple[str, str, str]], for_autocomplete: bool = False) -> SearchVector: ...

class Index:
    backend: PostgresSearchBackend
    def __init__(self, backend: PostgresSearchBackend) -> None: ...
    def add_model(self, model: type) -> None: ...
    def refresh(self) -> None: ...
    def delete_stale_model_entries(self, model: type) -> None: ...
    def delete_stale_entries(self) -> None: ...
    def add_item(self, obj: models.Model) -> None: ...
    def add_items(self, model: type, objs: Iterable[models.Model]) -> None: ...
    def delete_item(self, item: models.Model) -> None: ...

class PostgresSearchQueryCompiler(BaseSearchQueryCompiler):
    DEFAULT_OPERATOR: str
    LAST_TERM_IS_PREFIX: bool
    TARGET_SEARCH_FIELD_TYPE: type[SearchField]

class PostgresAutocompleteQueryCompiler(PostgresSearchQueryCompiler):
    LAST_TERM_IS_PREFIX: bool
    TARGET_SEARCH_FIELD_TYPE: type[AutocompleteField]

class PostgresSearchResults(BaseSearchResults):
    supports_facet: bool
    def get_queryset(self, for_count: bool = False) -> QuerySet[models.Model]: ...
    def facet(self, field_name: str) -> dict[str, int]: ...

class PostgresSearchRebuilder:
    index: Index
    def __init__(self, index: Index) -> None: ...
    def start(self) -> Index: ...
    def finish(self) -> None: ...

class PostgresSearchAtomicRebuilder(PostgresSearchRebuilder):
    def __init__(self, index: Index) -> None: ...
    def start(self) -> Index: ...
    def finish(self) -> None: ...

class PostgresSearchBackend(BaseSearchBackend):
    query_compiler_class: type[PostgresSearchQueryCompiler]
    autocomplete_query_compiler_class: type[PostgresAutocompleteQueryCompiler]
    results_class: type[PostgresSearchResults]
    rebuilder_class: type[PostgresSearchRebuilder]
    atomic_rebuilder_class: type[PostgresSearchAtomicRebuilder]
    def __init__(self, params: dict[str, Any]) -> None: ...
    def get_index_for_model(self, model: type) -> Index: ...
    def get_index_for_object(self, obj: models.Model) -> Index: ...
    def reset_index(self) -> None: ...
    def add_type(self, model: type) -> None: ...
    def refresh_index(self) -> None: ...
    def add(self, obj: models.Model) -> None: ...
    def add_bulk(self, model: type, obj_list: Iterable[models.Model]) -> None: ...
    def delete(self, obj: models.Model) -> None: ...

SearchBackend = PostgresSearchBackend
