from typing import Any, Dict, Optional, TypeVar, Union

from django.db.models.expressions import Combinable, CombinedExpression, Func, Value
from django.db.models.lookups import Lookup

from django.db.models import Field

class SearchVectorExact(Lookup): ...
class SearchVectorField(Field): ...
class SearchQueryField(Field): ...

class SearchVectorCombinable:
    ADD: str = ...

class SearchVector(SearchVectorCombinable, Func):
    config: Optional[Any] = None
    def __init__(self, *expressions: Union[str, Combinable], **extra: Any): ...

class CombinedSearchVector(SearchVectorCombinable, CombinedExpression):
    def __init__(self, lhs, connector, rhs, config, output_field: Optional[Field, str] = ...): ...

_T = TypeVar("_T", bound="SearchQueryCombinable")

class SearchQueryCombinable:
    BITAND: str = ...
    BITOR: str = ...
    def __or__(self: _T, other: SearchQueryCombinable) -> _T: ...
    def __ror__(self: _T, other: SearchQueryCombinable) -> _T: ...
    def __and__(self: _T, other: SearchQueryCombinable) -> _T: ...
    def __rand__(self: _T, other: SearchQueryCombinable) -> _T: ...

class SearchQuery(SearchQueryCombinable, Value):
    SEARCH_TYPES: Dict[str, str] = {"plain": "plainto_tsquery", "phrase": "phraseto_tsquery", "raw": "to_tsquery"}
    def __init__(self, value, output_field=None, *, config=None, invert=False, search_type="plain"): ...
    def __invert__(self: _T) -> _T: ...

class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression):
    def __init__(self, lhs, connector, rhs, config, output_field=None) -> None: ...

class SearchRank(Func):
    def __init__(self, vector, query, **extra: Any) -> None: ...

class TrigramBase(Func):
    def __init__(self, expression, string, **extra: Any) -> None: ...

class TrigramSimilarity(TrigramBase): ...
class TrigramDistance(TrigramBase): ...
