from collections.abc import Iterator
from typing import Any, Self

from django.db.models import Q
from django.db.models.query import ModelIterable
from treebeard.mp_tree import MP_Node, MP_NodeQuerySet
from wagtail.models import Page, Site
from wagtail.search.queryset import SearchableQuerySetMixin as SearchableQuerySetMixin

class TreeQuerySet(MP_NodeQuerySet):
    def delete(self) -> None: ...
    def descendant_of_q(self, other: MP_Node, inclusive: bool = False) -> Q: ...
    def descendant_of(self, other: MP_Node, inclusive: bool = False) -> TreeQuerySet: ...
    def not_descendant_of(self, other: MP_Node, inclusive: bool = False) -> TreeQuerySet: ...
    def child_of_q(self, other: MP_Node) -> Q: ...
    def child_of(self, other: MP_Node) -> TreeQuerySet: ...
    def not_child_of(self, other: MP_Node) -> TreeQuerySet: ...
    def ancestor_of_q(self, other: MP_Node, inclusive: bool = False) -> Q: ...
    def ancestor_of(self, other: MP_Node, inclusive: bool = False) -> TreeQuerySet: ...
    def not_ancestor_of(self, other: MP_Node, inclusive: bool = False) -> TreeQuerySet: ...
    def parent_of_q(self, other: MP_Node) -> Q: ...
    def parent_of(self, other: MP_Node) -> TreeQuerySet: ...
    def not_parent_of(self, other: MP_Node) -> TreeQuerySet: ...
    def sibling_of_q(self, other: MP_Node, inclusive: bool = True) -> Q: ...
    def sibling_of(self, other: MP_Node, inclusive: bool = True) -> TreeQuerySet: ...
    def not_sibling_of(self, other: MP_Node, inclusive: bool = True) -> TreeQuerySet: ...

class SpecificQuerySetMixin:
    _defer_streamfields: bool
    _specific_select_related_fields: tuple[str, ...]
    _specific_prefetch_related_lookups: tuple[str, ...]
    def __init__(self, *args: Any, **kwargs: Any) -> None: ...
    def specific(self, defer: bool = False) -> Self: ...
    @property
    def is_specific(self) -> bool: ...
    def select_related(self, *fields: str, for_specific_subqueries: bool = False) -> Self: ...
    def prefetch_related(self, *lookups: str, for_specific_subqueries: bool = False) -> Self: ...

class PageQuerySet(SearchableQuerySetMixin, SpecificQuerySetMixin, TreeQuerySet):
    def live_q(self) -> Q: ...
    def live(self) -> PageQuerySet: ...
    def not_live(self) -> PageQuerySet: ...
    def in_menu_q(self) -> Q: ...
    def in_menu(self) -> PageQuerySet: ...
    def not_in_menu(self) -> PageQuerySet: ...
    def page_q(self, other: Page) -> Q: ...
    def page(self, other: Page) -> PageQuerySet: ...
    def not_page(self, other: Page) -> PageQuerySet: ...
    def type_q(self, *types: type) -> Q: ...
    def type(self, *types: type) -> PageQuerySet: ...
    def not_type(self, *types: type) -> PageQuerySet: ...
    def exact_type_q(self, *types: type) -> Q: ...
    def exact_type(self, *types: type) -> PageQuerySet: ...
    def not_exact_type(self, *types: type) -> PageQuerySet: ...
    def private_q(self) -> Q: ...
    def public(self) -> PageQuerySet: ...
    def not_public(self) -> PageQuerySet: ...
    def private(self) -> PageQuerySet: ...
    def first_common_ancestor(self, include_self: bool = False, strict: bool = False) -> Page: ...
    def unpublish(self) -> None: ...
    def defer_streamfields(self) -> PageQuerySet: ...
    def in_site(self, site: Site) -> PageQuerySet: ...
    def translation_of_q(self, page: Page, inclusive: bool) -> Q: ...
    def translation_of(self, page: Page, inclusive: bool = False) -> PageQuerySet: ...
    def not_translation_of(self, page: Page, inclusive: bool = False) -> PageQuerySet: ...
    def prefetch_workflow_states(self) -> PageQuerySet: ...
    def annotate_approved_schedule(self) -> PageQuerySet: ...
    def annotate_site_root_state(self) -> PageQuerySet: ...
    def annotate_has_untranslated_locale(self) -> PageQuerySet: ...

class SpecificIterable(ModelIterable):
    def __iter__(self) -> Iterator[Page]: ...

class DeferredSpecificIterable(ModelIterable):
    def __iter__(self) -> Iterator[Page]: ...
