import threading
from collections.abc import Callable, Iterable
from typing import Literal, overload, Any

from django.db.models.base import Model

from .config import AppConfig
from api.models import APIToken, OutboundWebhook
from core.models import ArchiveResult, Snapshot, SnapshotTag, Tag
from django.contrib.admin.models import LogEntry
from django.contrib.auth.models import Group, Permission, User
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.models import Session

class Apps:
    all_models: dict[str, dict[str, type[Model]]]
    app_configs: dict[str, AppConfig]
    stored_app_configs: list[Any]
    apps_ready: bool
    ready_event: threading.Event
    loading: bool
    _pending_operations: dict[tuple[str, str], list]
    models_ready: bool
    ready: bool
    def __init__(self, installed_apps: Iterable[AppConfig | str] | None = ...) -> None: ...
    def populate(self, installed_apps: Iterable[AppConfig | str] | None = ...) -> None: ...
    def check_apps_ready(self) -> None: ...
    def check_models_ready(self) -> None: ...
    def get_app_configs(self) -> Iterable[AppConfig]: ...
    def get_app_config(self, app_label: str) -> AppConfig: ...
    # it's not possible to support it in plugin properly now
    def get_models(self, include_auto_created: bool = ..., include_swapped: bool = ...) -> list[type[Model]]: ...
    @overload
    def get_model(self, app_label: Literal["auth.Permission"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[Permission]: ...
    @overload
    def get_model(self, app_label: Literal["auth"], model_name: Literal["Permission"], require_ready: bool = ...) -> type[Permission]: ...
    @overload
    def get_model(self, app_label: Literal["auth.Group"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[Group]: ...
    @overload
    def get_model(self, app_label: Literal["auth"], model_name: Literal["Group"], require_ready: bool = ...) -> type[Group]: ...
    @overload
    def get_model(self, app_label: Literal["auth.User"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[User]: ...
    @overload
    def get_model(self, app_label: Literal["auth"], model_name: Literal["User"], require_ready: bool = ...) -> type[User]: ...
    @overload
    def get_model(self, app_label: Literal["contenttypes.ContentType"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[ContentType]: ...
    @overload
    def get_model(self, app_label: Literal["contenttypes"], model_name: Literal["ContentType"], require_ready: bool = ...) -> type[ContentType]: ...
    @overload
    def get_model(self, app_label: Literal["sessions.Session"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[Session]: ...
    @overload
    def get_model(self, app_label: Literal["sessions"], model_name: Literal["Session"], require_ready: bool = ...) -> type[Session]: ...
    @overload
    def get_model(self, app_label: Literal["admin.LogEntry"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[LogEntry]: ...
    @overload
    def get_model(self, app_label: Literal["admin"], model_name: Literal["LogEntry"], require_ready: bool = ...) -> type[LogEntry]: ...
    @overload
    def get_model(self, app_label: Literal["core.Tag"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[Tag]: ...
    @overload
    def get_model(self, app_label: Literal["core"], model_name: Literal["Tag"], require_ready: bool = ...) -> type[Tag]: ...
    @overload
    def get_model(self, app_label: Literal["core.SnapshotTag"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[SnapshotTag]: ...
    @overload
    def get_model(self, app_label: Literal["core"], model_name: Literal["SnapshotTag"], require_ready: bool = ...) -> type[SnapshotTag]: ...
    @overload
    def get_model(self, app_label: Literal["core.Snapshot"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[Snapshot]: ...
    @overload
    def get_model(self, app_label: Literal["core"], model_name: Literal["Snapshot"], require_ready: bool = ...) -> type[Snapshot]: ...
    @overload
    def get_model(self, app_label: Literal["core.ArchiveResult"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[ArchiveResult]: ...
    @overload
    def get_model(self, app_label: Literal["core"], model_name: Literal["ArchiveResult"], require_ready: bool = ...) -> type[ArchiveResult]: ...
    @overload
    def get_model(self, app_label: Literal["api.APIToken"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[APIToken]: ...
    @overload
    def get_model(self, app_label: Literal["api"], model_name: Literal["APIToken"], require_ready: bool = ...) -> type[APIToken]: ...
    @overload
    def get_model(self, app_label: Literal["api.OutboundWebhook"], model_name: Literal[None] = ..., require_ready: bool = ...) -> type[OutboundWebhook]: ...
    @overload
    def get_model(self, app_label: Literal["api"], model_name: Literal["OutboundWebhook"], require_ready: bool = ...) -> type[OutboundWebhook]: ...
    def register_model(self, app_label: str, model: type[Model]) -> None: ...
    def is_installed(self, app_name: str) -> bool: ...
    def get_containing_app_config(self, object_name: str) -> AppConfig | None: ...
    def get_registered_model(self, app_label: str, model_name: str) -> type[Model]: ...
    def get_swappable_settings_name(self, to_string: str) -> str | None: ...
    def set_available_apps(self, available: Iterable[str]) -> None: ...
    def unset_available_apps(self) -> None: ...
    def set_installed_apps(self, installed: Iterable[str]) -> None: ...
    def unset_installed_apps(self) -> None: ...
    def clear_cache(self) -> None: ...
    def lazy_model_operation(self, function: Callable, *model_keys: Any) -> None: ...
    def do_pending_operations(self, model: type[Model]) -> None: ...

apps: Apps
