from typing import Any, Callable, Dict, Optional, Sequence, Type, Union

from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
from typing_extensions import Literal

from django.db import models
from django.forms import Form
from django.http import HttpRequest, HttpResponse

class FormMixin(ContextMixin):
    initial: Dict[str, Any] = ...
    form_class: Optional[Type[Form]] = ...
    success_url: Optional[Union[str, Callable[..., Any]]] = ...
    prefix: Optional[str] = ...
    request: HttpRequest = ...
    def render_to_response(self, context: Dict[str, Any], **response_kwargs: object) -> HttpResponse: ...
    def get_initial(self) -> Dict[str, Any]: ...
    def get_prefix(self) -> Optional[str]: ...
    def get_form_class(self) -> Type[Form]: ...
    def get_form(self, form_class: Type[Form] = None) -> Form: ...
    def get_form_kwargs(self) -> Dict[str, Any]: ...
    def get_success_url(self) -> str: ...
    def form_valid(self, form: Form) -> HttpResponse: ...
    def form_invalid(self, form: Form) -> HttpResponse: ...
    def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...

class ModelFormMixin(FormMixin, SingleObjectMixin):
    fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ...
    object: models.Model = ...
    def get_form_class(self) -> Type[Form]: ...
    def get_form_kwargs(self) -> Dict[str, object]: ...
    def get_success_url(self) -> str: ...
    def form_valid(self, form: Form) -> HttpResponse: ...

class ProcessFormView(View):
    def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
    def get_context_data(self, **kwargs: object) -> Dict[str, Any]: ...
    def get_form(self, form_class: Type[Form] = None) -> Form: ...
    def form_valid(self, form: Form) -> HttpResponse: ...
    def form_invalid(self, form: Form) -> HttpResponse: ...
    def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def put(self, *args: Any, **kwargs: Any) -> HttpResponse: ...

class BaseFormView(FormMixin, ProcessFormView): ...
class FormView(TemplateResponseMixin, BaseFormView): ...

class BaseCreateView(ModelFormMixin, ProcessFormView):
    object = ...  # type: models.Model
    def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...

class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
    template_name_suffix = ...  # type: str

class BaseUpdateView(ModelFormMixin, ProcessFormView):
    object = ...  # type: models.Model
    def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...

class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
    template_name_suffix = ...  # type: str

_object = object

class DeletionMixin:
    success_url = ...  # type: Optional[str]
    object = ...  # type: models.Model
    def delete(self, request: HttpRequest, *args: _object, **kwargs: _object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: _object, **kwargs: _object) -> HttpResponse: ...
    def get_success_url(self) -> str: ...

class BaseDeleteView(DeletionMixin, BaseDetailView): ...

class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
    template_name_suffix = ...  # type: str
