from collections.abc import Callable, Sequence
from typing import Any, Generic, Literal, TypeVar

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,
)

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

class AbstractFormMixin(ContextMixin):
    initial: dict[str, Any] = ...
    form_class: type[BaseForm] | None = ...
    success_url: str | Callable[..., Any] | None = ...
    prefix: str | None = ...
    def get_initial(self) -> dict[str, Any]: ...
    def get_prefix(self) -> str | None: ...
    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: type[_FormT] | None = ...) -> BaseForm: ...
    def form_valid(self, form: _FormT) -> HttpResponse: ...
    def form_invalid(self, form: _FormT) -> HttpResponse: ...

class ModelFormMixin(AbstractFormMixin, SingleObjectMixin):
    fields: Sequence[str] | Literal["__all__"] | None = ...
    def get_form_class(self) -> type[BaseModelForm]: ...
    def get_form(
        self, form_class: type[BaseModelForm] | None = ...
    ) -> 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: str | None = ...
    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): ...
