from collections.abc import Iterable
from typing import Any, ClassVar, Self

from django.db import models
from django.db.models import QuerySet
from treebeard.ltree.fields import PathField as PathField
from treebeard.ltree.fields import PathValue as PathValue
from treebeard.models import Node

class InvalidLabelConstraints(Exception): ...

def generate_label(
    skip: set[str],
    before: str | None = ...,
    after: str | None = ...,
) -> str: ...
def generate_path(
    prefix: PathValue | None = ...,
    before: str | None = ...,
    after: str | None = ...,
    skip: Iterable[PathValue] | None = ...,
) -> PathValue: ...

class LT_NodeQuerySet(models.QuerySet["LT_Node"]):
    def delete(self, *args: Any, **kwargs: Any) -> tuple[int, dict[str, int]]: ...

class LT_NodeManager(models.Manager["LT_Node"]):
    def get_queryset(self) -> LT_NodeQuerySet: ...

class LT_ComplexAddMoveHandler: ...

class LT_AddRootHandler:
    cls: type[LT_Node]
    kwargs: dict[str, Any]
    def __init__(self, cls: type[LT_Node], **kwargs: Any) -> None: ...
    def process(self) -> LT_Node: ...

class LT_AddChildHandler:
    node: LT_Node
    node_cls: type[LT_Node]
    kwargs: dict[str, Any]
    def __init__(self, node: LT_Node, creation_kwargs: dict[str, Any]) -> None: ...
    def process(self) -> LT_Node: ...

class LT_AddSiblingHandler(LT_ComplexAddMoveHandler):
    node: LT_Node
    node_cls: type[LT_Node]
    pos: str
    kwargs: dict[str, Any]
    def __init__(self, node: LT_Node, pos: str | None, creation_kwargs: dict[str, Any]) -> None: ...
    def process(self) -> LT_Node: ...

class LT_MoveHandler(LT_ComplexAddMoveHandler):
    node: LT_Node
    node_cls: type[LT_Node]
    target: LT_Node
    pos: str | None
    def __init__(self, node: LT_Node, target: LT_Node, pos: str | None = ...) -> None: ...
    def process(self) -> None: ...

class LT_Node(Node):
    node_order_by: list[str]
    path: PathField

    TREEBEARD_IDENTIFYING_FIELD: str
    MOVENODE_FORM_EXCLUDED_FIELDS: tuple[str, ...]

    objects: ClassVar[LT_NodeManager]  # type: ignore[assignment]

    @classmethod
    def add_root(cls, **kwargs: Any) -> Self: ...
    @classmethod
    def dump_bulk(cls, parent: Self | None = ..., keep_ids: bool = ...) -> list[dict[str, Any]]: ...
    @classmethod
    def get_tree(cls, parent: Self | None = ...) -> QuerySet[Self]: ...
    @classmethod
    def get_root_nodes(cls) -> QuerySet[Self]: ...
    @classmethod
    def get_descendants_group_count(cls, parent: Self | None = ...) -> QuerySet[Self]: ...
    def get_depth(self) -> int: ...
    def get_siblings(self) -> QuerySet[Self]: ...
    def get_children(self) -> QuerySet[Self]: ...
    def get_next_sibling(self) -> Self | None: ...
    def get_descendants(self, include_self: bool = ...) -> QuerySet[Self]: ...
    def get_prev_sibling(self) -> Self | None: ...
    def get_children_count(self) -> int: ...
    def is_sibling_of(self, node: Self) -> bool: ...
    def is_child_of(self, node: Self) -> bool: ...
    def is_descendant_of(self, node: Self) -> bool: ...
    def add_child(self, **kwargs: Any) -> Self: ...
    def add_sibling(self, pos: str | None = ..., **kwargs: Any) -> Self: ...
    def get_root(self) -> Self: ...
    def is_root(self) -> bool: ...
    def is_leaf(self) -> bool: ...
    def get_ancestors(self) -> QuerySet[Self]: ...
    def get_parent(self, update: bool = ...) -> Self | None: ...
    def move(self, target: Self, pos: str | None = ...) -> None: ...

    class Meta:
        abstract: bool
