import collections
from collections.abc import Callable, Sequence
from datetime import datetime
from typing import Any
from uuid import UUID

from django.contrib.admin.options import BaseModelAdmin
from django.contrib.admin.sites import AdminSite
from django.contrib.auth.forms import AdminPasswordChangeForm
from django.core.handlers.wsgi import WSGIRequest
from django.db.models.base import Model
from django.db.models.deletion import Collector
from django.db.models.fields import Field, reverse_related
from django.db.models.fields.reverse_related import ManyToOneRel
from django.db.models.options import Options
from django.db.models.query import QuerySet
from django.forms.forms import BaseForm

class FieldIsAForeignKeyColumnName(Exception): ...

def lookup_needs_distinct(opts: Options[Any], lookup_path: str) -> bool: ...
def prepare_lookup_value(key: str, value: datetime | str) -> bool | datetime | str: ...
def quote(s: int | str | UUID) -> str: ...
def unquote(s: str) -> str: ...
def flatten(fields: Any) -> list[Callable[..., Any] | str]: ...
def flatten_fieldsets(fieldsets: Any) -> list[Callable[..., Any] | str]: ...
def get_deleted_objects(
    objs: Sequence[Model | None], request: WSGIRequest, admin_site: AdminSite
) -> tuple[list[Any], dict[Any, Any], set[Any], list[Any]]: ...

class NestedObjects(Collector):
    data: collections.OrderedDict[Any, Any]
    dependencies: dict[Any, Any]
    fast_deletes: list[Any]
    field_updates: dict[Any, Any]
    using: str
    edges: Any = ...
    protected: Any = ...
    model_objs: Any = ...
    def __init__(self, *args: Any, **kwargs: Any) -> None: ...
    def add_edge(self, source: Model | None, target: Model) -> None: ...
    def related_objects(
        self, related: ManyToOneRel, objs: Sequence[Model | None]
    ) -> QuerySet[Any]: ...
    def nested(self, format_callback: Callable[..., Any] = ...) -> list[Any]: ...

def model_format_dict(obj: Any) -> Any: ...
def model_ngettext(obj: Options[Any] | QuerySet[Any], n: int | None = ...) -> str: ...
def lookup_field(
    name: Callable[..., Any] | str,
    obj: Model,
    model_admin: BaseModelAdmin[Any] = ...,
) -> tuple[Field[Any, Any] | None, Any, Any]: ...
def label_for_field(
    name: Callable[..., Any] | str,
    model: type[Model],
    model_admin: BaseModelAdmin[Any] | None = ...,
    return_attr: bool = ...,
    form: BaseForm | None = ...,
) -> tuple[str | None, Callable[..., Any] | type[str]] | str: ...
def help_text_for_field(name: str, model: type[Model]) -> str: ...
def display_for_field(
    value: Any, field: Field[Any, Any], empty_value_display: str
) -> str: ...
def display_for_value(
    value: Any, empty_value_display: str, boolean: bool = ...
) -> str: ...

class NotRelationField(Exception): ...

def get_model_from_relation(
    field: Field[Any, Any] | reverse_related.ForeignObjectRel
) -> type[Model]: ...
def reverse_field_path(model: type[Model], path: str) -> tuple[type[Model], str]: ...
def get_fields_from_path(model: type[Model], path: str) -> list[Field[Any, Any]]: ...
def construct_change_message(
    form: AdminPasswordChangeForm, formsets: None, add: bool
) -> list[dict[str, dict[str, list[str]]]]: ...
