from typing import Any, Generic, Optional, Sequence, Tuple, Type, TypeVar

from django.core.paginator import Paginator
from django.db.models import Model
from django.db.models.query import QuerySet
from django.http import HttpRequest, HttpResponse
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View

T = TypeVar("T", bound=Model, covariant=True)

class MultipleObjectMixin(Generic[T], ContextMixin):
    allow_empty: bool = ...
    queryset: Optional[QuerySet[T]] = ...
    model: Optional[Type[T]] = ...
    paginate_by: int = ...
    paginate_orphans: int = ...
    context_object_name: Optional[str] = ...
    paginator_class: Type[Paginator] = ...
    page_kwarg: str = ...
    ordering: Sequence[str] = ...
    def get_queryset(self) -> QuerySet[T]: ...
    def get_ordering(self) -> Sequence[str]: ...
    def paginate_queryset(self, queryset: QuerySet, page_size: int) -> Tuple[Paginator, int, QuerySet[T], bool]: ...
    def get_paginate_by(self, queryset: QuerySet) -> Optional[int]: ...
    def get_paginator(
        self, queryset: QuerySet, per_page: int, orphans: int = ..., allow_empty_first_page: bool = ..., **kwargs: Any
    ) -> Paginator: ...
    def get_paginate_orphans(self) -> int: ...
    def get_allow_empty(self) -> bool: ...
    def get_context_object_name(self, object_list: QuerySet) -> Optional[str]: ...

class BaseListView(MultipleObjectMixin[T], View):
    object_list: Sequence[T]
    def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...

class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
    template_name_suffix: str = ...

class ListView(MultipleObjectTemplateResponseMixin, BaseListView[T]): ...
