import datetime
from typing import Any, Dict, Optional, Sequence, Tuple

from django.db import models
from django.http import HttpRequest, HttpResponse
from django.views.generic.base import View
from django.views.generic.detail import (
    BaseDetailView,
    SingleObjectTemplateResponseMixin,
)
from django.views.generic.list import (
    MultipleObjectMixin,
    MultipleObjectTemplateResponseMixin,
)

class YearMixin:
    year_format: str = ...
    year: Optional[str] = ...
    def get_year_format(self) -> str: ...
    def get_year(self) -> str: ...
    def get_next_year(self, date: datetime.date) -> Optional[datetime.date]: ...
    def get_previous_year(self, date: datetime.date) -> Optional[datetime.date]: ...

class MonthMixin:
    month_format: str = ...
    month: Optional[str] = ...
    def get_month_format(self) -> str: ...
    def get_month(self) -> str: ...
    def get_next_month(self, date: datetime.date) -> Optional[datetime.date]: ...
    def get_previous_month(self, date: datetime.date) -> Optional[datetime.date]: ...

class DayMixin:
    day_format: str = ...
    day: Optional[str] = ...
    def get_day_format(self) -> str: ...
    def get_day(self) -> str: ...
    def get_next_day(self, date: datetime.date) -> Optional[datetime.date]: ...
    def get_previous_day(self, date: datetime.date) -> Optional[datetime.date]: ...

class WeekMixin:
    week_format: str = ...
    week: Optional[str] = ...
    def get_week_format(self) -> str: ...
    def get_week(self) -> str: ...
    def get_next_week(self, date: datetime.date) -> Optional[datetime.date]: ...
    def get_previous_week(self, date: datetime.date) -> Optional[datetime.date]: ...

class DateMixin:
    date_field: Optional[str] = ...
    allow_future: bool = ...
    def get_date_field(self) -> str: ...
    def get_allow_future(self) -> bool: ...
    def uses_datetime_field(self) -> bool: ...

DatedItems = Tuple[Optional[Sequence[datetime.date]], Sequence[object], Dict[str, Any]]

class BaseDateListView(MultipleObjectMixin, DateMixin, View):
    date_list_period: str = ...
    def render_to_response(
        self, context: Dict[str, Any], **response_kwargs: Any
    ) -> HttpResponse: ...
    def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...
    def get_dated_items(self) -> DatedItems: ...
    def get_dated_queryset(self, **lookup: Any) -> models.query.QuerySet[Any]: ...
    def get_date_list_period(self) -> str: ...
    def get_date_list(
        self,
        queryset: models.query.QuerySet[Any],
        date_type: Optional[str] = ...,
        ordering: str = ...,
    ) -> models.query.QuerySet[Any]: ...

class BaseArchiveIndexView(BaseDateListView): ...
class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView): ...

class BaseYearArchiveView(YearMixin, BaseDateListView):
    make_object_list: bool = ...
    def get_make_object_list(self) -> bool: ...

class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView): ...
class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView): ...
class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView): ...
class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView): ...
class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView): ...
class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView): ...
class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView): ...
class BaseTodayArchiveView(BaseDayArchiveView): ...
class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView): ...
class BaseDateDetailView(
    YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView
): ...
class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView): ...

def timezone_today() -> datetime.date: ...
