from collections.abc import Callable, Iterator, Sequence
from typing import Any, Generic, TypeVar

from django.apps.config import AppConfig
from django.apps.registry import Apps
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.postgres.fields.array import ArrayField
from django.contrib.postgres.fields.citext import CIText
from django.db.backends.sqlite3.base import DatabaseWrapper
from django.db.models.base import Model
from django.db.models.constraints import BaseConstraint
from django.db.models.fields import AutoField, Field
from django.db.models.fields.mixins import FieldCacheMixin
from django.db.models.fields.related import ManyToManyField, OneToOneField
from django.db.models.fields.reverse_related import ForeignObjectRel
from django.db.models.manager import Manager
from django.db.models.query_utils import PathInfo
from django.utils.datastructures import ImmutableList

PROXY_PARENTS: Any
EMPTY_RELATION_TREE: Any
IMMUTABLE_WARNING: str
DEFAULT_NAMES: tuple[str, ...]

def normalize_together(
    option_together: Sequence[tuple[str, str]] | tuple[str, str]
) -> tuple[tuple[str, str], ...]: ...
def make_immutable_fields_list(
    name: str,
    data: (
        Iterator[Any]
        | list[ArrayField[Any] | CIText]
        | list[Field[Any, Any] | FieldCacheMixin]
    ),
) -> ImmutableList[Any]: ...

_M = TypeVar("_M", bound=Model)

class Options(Generic[_M]):
    base_manager: Manager[Any]
    concrete_fields: ImmutableList[Any]
    constraints: list[BaseConstraint]
    default_manager: Manager[_M]
    fields: ImmutableList[Any]
    local_concrete_fields: ImmutableList[Any]
    related_objects: ImmutableList[Any]
    FORWARD_PROPERTIES: Any = ...
    REVERSE_PROPERTIES: Any = ...
    default_apps: Any = ...
    local_fields: list[Field[Any, Any]] = ...
    local_many_to_many: list[ManyToManyField[Any, Any]] = ...
    private_fields: list[Any] = ...
    local_managers: list[Manager[Any]] = ...
    base_manager_name: str | None = ...
    default_manager_name: str | None = ...
    model_name: str | None = ...
    verbose_name: str | None = ...
    verbose_name_plural: str | None = ...
    db_table: str = ...
    ordering: Sequence[str] | None = ...
    indexes: list[Any] = ...
    unique_together: list[Any] | tuple[Any, ...] = ...
    index_together: list[Any] | tuple[Any, ...] = ...
    select_on_save: bool = ...
    default_permissions: Sequence[str] = ...
    permissions: list[Any] = ...
    object_name: str | None = ...
    app_label: str = ...
    get_latest_by: Sequence[str] | None = ...
    order_with_respect_to: None = ...
    db_tablespace: str = ...
    required_db_features: list[Any] = ...
    required_db_vendor: None = ...
    meta: type | None = ...
    pk: Field[Any, Any] | None = ...
    auto_field: AutoField | None = ...
    abstract: bool = ...
    managed: bool = ...
    proxy: bool = ...
    proxy_for_model: type[_M] | None = ...
    concrete_model: type[_M] | None = ...
    swappable: None = ...
    parents: dict[Any, Any] = ...
    auto_created: bool = ...
    related_fkey_lookups: list[Any] = ...
    apps: Apps = ...
    default_related_name: str | None = ...
    model: type[_M] = ...
    original_attrs: dict[str, Any] = ...
    def __init__(self, meta: type | None, app_label: str | None = ...) -> None: ...
    @property
    def label(self) -> str: ...
    @property
    def label_lower(self) -> str: ...
    @property
    def app_config(self) -> AppConfig: ...
    @property
    def installed(self) -> Any: ...
    def contribute_to_class(self, cls: type[Model], name: str) -> None: ...
    def add_manager(self, manager: Manager[Any]) -> None: ...
    def add_field(
        self, field: GenericForeignKey | Field[Any, Any], private: bool = ...
    ) -> None: ...
    def setup_pk(self, field: Field[Any, Any]) -> None: ...
    def setup_proxy(self, target: type[Model]) -> None: ...
    def can_migrate(self, connection: DatabaseWrapper | str) -> bool: ...
    @property
    def verbose_name_raw(self) -> str: ...
    @property
    def swapped(self) -> str | None: ...
    @property
    def many_to_many(self) -> list[ManyToManyField[Any, Any]]: ...
    @property
    def fields_map(self) -> dict[str, Field[Any, Any] | ForeignObjectRel]: ...
    @property
    def managers(self) -> list[Manager[Any]]: ...
    @property
    def managers_map(self) -> dict[str, Manager[Any]]: ...
    @property
    def db_returning_fields(self) -> list[Field[Any, Any]]: ...
    def get_field(self, field_name: Callable[..., Any] | str) -> Field[Any, Any]: ...
    def get_base_chain(self, model: type[Model]) -> list[type[Model]]: ...
    def get_parent_list(self) -> list[type[Model]]: ...
    def get_ancestor_link(self, ancestor: type[Model]) -> OneToOneField[Any] | None: ...
    def get_path_to_parent(self, parent: type[Model]) -> list[PathInfo]: ...
    def get_path_from_parent(self, parent: type[Model]) -> list[PathInfo]: ...
    def get_fields(
        self, include_parents: bool = ..., include_hidden: bool = ...
    ) -> list[Field[Any, Any] | ForeignObjectRel]: ...
