from collections.abc import Callable, Iterable, Iterator
from types import TracebackType
from typing import Any, TypeAlias

from django.http.request import HttpRequest
from django.template.base import Node, Origin, Template
from django.template.defaulttags import IfChangedNode
from django.template.loader_tags import IncludeNode

_ContextValues: TypeAlias = dict[str, Any] | Context

class ContextPopException(Exception): ...

class ContextDict(dict[Any, Any]):
    context: BaseContext = ...
    def __init__(self, context: BaseContext, *args: Any, **kwargs: Any) -> None: ...
    def __enter__(self) -> ContextDict: ...
    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_value: BaseException | None,
        traceback: TracebackType | None,
    ) -> None: ...

class BaseContext(Iterable[Any]):
    def __init__(self, dict_: Any = ...) -> None: ...
    def __copy__(self) -> BaseContext: ...
    def __iter__(self) -> Iterator[Any]: ...
    def push(self, *args: Any, **kwargs: Any) -> ContextDict: ...
    def pop(self) -> ContextDict: ...
    def __setitem__(self, key: Node | str, value: Any) -> None: ...
    def set_upward(self, key: str, value: int | str) -> None: ...
    def __getitem__(self, key: int | str) -> Any: ...
    def __delitem__(self, key: Any) -> None: ...
    def __contains__(self, key: str) -> bool: ...
    def get(self, key: str, otherwise: Any | None = ...) -> Any | None: ...
    def setdefault(
        self,
        key: IfChangedNode | str,
        default: list[Origin] | int | None = ...,
    ) -> list[Origin] | int | None: ...
    def new(self, values: _ContextValues | None = ...) -> Context: ...
    def flatten(
        self,
    ) -> dict[str, dict[str, type[Any] | str] | int | str | None]: ...

class Context(BaseContext):
    dicts: Any
    autoescape: bool = ...
    use_l10n: bool | None = ...
    use_tz: bool | None = ...
    template_name: str | None = ...
    render_context: RenderContext = ...
    template: Template | None = ...
    def __init__(
        self,
        dict_: Any = ...,
        autoescape: bool = ...,
        use_l10n: bool | None = ...,
        use_tz: None = ...,
    ) -> None: ...
    def bind_template(self, template: Template) -> Iterator[None]: ...
    def update(self, other_dict: dict[str, Any] | Context) -> ContextDict: ...

class RenderContext(BaseContext):
    dicts: list[dict[IncludeNode | str, str]]
    template: Template | None = ...
    def push_state(
        self, template: Template, isolated_context: bool = ...
    ) -> Iterator[None]: ...

class RequestContext(Context):
    autoescape: bool
    dicts: list[dict[str, str]]
    render_context: RenderContext
    template_name: str | None
    use_l10n: None  # pyright: ignore[reportIncompatibleVariableOverride]
    use_tz: None  # pyright: ignore[reportIncompatibleVariableOverride]
    request: HttpRequest = ...
    def __init__(
        self,
        request: HttpRequest,
        dict_: dict[str, Any] | None = ...,
        processors: list[Callable[..., Any]] | None = ...,
        use_l10n: None = ...,
        use_tz: None = ...,
        autoescape: bool = ...,
    ) -> None: ...
    template: Template | None = ...
    def bind_template(self, template: Template) -> Iterator[None]: ...
    def new(self, values: _ContextValues | None = ...) -> RequestContext: ...

def make_context(
    context: Any, request: HttpRequest | None = ..., **kwargs: Any
) -> Context: ...
