from typing import (
    Any,
    Callable,
    Dict,
    Generic,
    Optional,
    Sequence,
    Type,
    TypeVar,
    Union,
)

from django.forms.forms import BaseForm
from django.forms.models import BaseModelForm
from django.http import HttpRequest, HttpResponse
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
from django.views.generic.detail import (
    BaseDetailView,
    SingleObjectMixin,
    SingleObjectTemplateResponseMixin,
)
from typing_extensions import Literal

_FormT = TypeVar("_FormT", bound=BaseForm)

class AbstractFormMixin(ContextMixin):
    initial: Dict[str, Any] = ...
    form_class: Optional[Type[BaseForm]] = ...
    success_url: Optional[Union[str, Callable[..., Any]]] = ...
    prefix: Optional[str] = ...
    def get_initial(self) -> Dict[str, Any]: ...
    def get_prefix(self) -> Optional[str]: ...
    def get_form_kwargs(self) -> Dict[str, Any]: ...
    def get_success_url(self) -> str: ...

class FormMixin(Generic[_FormT], AbstractFormMixin):
    def get_form_class(self) -> Type[_FormT]: ...
    def get_form(self, form_class: Optional[Type[_FormT]] = ...) -> BaseForm: ...
    def form_valid(self, form: _FormT) -> HttpResponse: ...
    def form_invalid(self, form: _FormT) -> HttpResponse: ...

class ModelFormMixin(AbstractFormMixin, SingleObjectMixin):
    fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ...
    def get_form_class(self) -> Type[BaseModelForm]: ...
    def get_form(
        self, form_class: Optional[Type[BaseModelForm]] = ...
    ) -> BaseModelForm: ...
    def form_valid(self, form: BaseModelForm) -> HttpResponse: ...
    def form_invalid(self, form: BaseModelForm) -> HttpResponse: ...

class ProcessFormView(View):
    def get(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
    def put(self, *args: str, **kwargs: Any) -> HttpResponse: ...

class BaseFormView(FormMixin[_FormT], ProcessFormView): ...
class FormView(TemplateResponseMixin, BaseFormView[_FormT]): ...
class BaseCreateView(ModelFormMixin, ProcessFormView): ...
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView): ...
class BaseUpdateView(ModelFormMixin, ProcessFormView): ...
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView): ...

class DeletionMixin:
    success_url: Optional[str] = ...
    def post(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
    def delete(
        self, request: HttpRequest, *args: str, **kwargs: Any
    ) -> HttpResponse: ...
    def get_success_url(self) -> str: ...

class BaseDeleteView(DeletionMixin, BaseDetailView): ...
class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView): ...
