import json

import pyexcel
from django.conf import settings
from django.contrib.auth import get_user_model, views as auth_views
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.db import models
from django.http import FileResponse, JsonResponse
from django.shortcuts import redirect
from django.urls import path, reverse_lazy
from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
                                  UpdateView)
from django.views.generic.base import TemplateView, View
from django.views.generic.edit import FormView
from rest_framework import status, viewsets
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from rest_framework.views import APIView

from .core import (get_color_from_class, get_global_history_model, get_href,
                   get_layout_data, get_model_fields)
from .forms import ImportXlsForm, get_generic_form
from .models import GenericModel
from .serializers import GenericSerializer, GenericUserSerializer


class GenericDashboardView(PermissionRequiredMixin, TemplateView):
    """
    Vue en tuile prenant en entrée une liste de modèles.
    """

    # models: list[GenericModel] = []
    models = []
    template_name = "django_bkendoz/dashboard.html"
    dflt_model_template = "django_bkendoz/dashboard_tpl.html"
    dflt_tile_class = "tile-simple-column"
    list_cls = "dashboard-list"
    auth = "superuser"

    def __init__(self, **kwargs):
        assert hasattr(
            settings, "DASH_LIST_COUNT"
        ), """
            DASH_LIST_COUNT non défini dans settings.py,
            il faut définir la valeur par default du nombre d'element à afficher dans le tableau de bord
            """
        self.permission_required = f"{self.auth}.dashboard"
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["models"] = {}
        for m in self.models:
            m_dict = context["models"][m] = {}
            o_cnt = m.get_view_data("dashboard", "count") or settings.DASH_LIST_COUNT
            o_ord = m.get_view_data("dashboard", "orderby") or None
            m_dict["title"] = m.get_view_data("dashboard", "title")
            m_dict["class"] = (
                m.get_view_data("dashboard", "class") or self.dflt_tile_class
            )
            m_dict["html"] = (
                m.get_view_data("dashboard", "html") or self.dflt_model_template
            )
            m_dict["menu"] = m.get_class_menu("dashboard")
            m_dict["fields"] = self.get_dash_fields(m)
            if o_ord:
                m_dict["list"] = m.objects.all().order_by(o_ord)[:o_cnt]
            else:
                m_dict["list"] = m.objects.all()[:o_cnt]

        context["layout_data"] = get_layout_data()
        context["settings"] = settings
        return context

    def get_dash_fields(self, model):
        """
        Retourne les champs à afficher dans la vue en tuile.
        :param model: model dont les champs sont à afficher
        :type model: GenericModel
        [str]: Liste de champs
        """
        view_struct_fields = model.get_view_data("dashboard")
        return get_model_fields(model, view_struct_fields)


class GenericOmnibarView(View):
    models = []
    data = []
    auth = "superuser"

    def __init__(self, **kwargs):
        self.permission_required = f"{self.auth}.omnibar"
        super().__init__(**kwargs)

    def get(self, request, *args, **kwargs):
        items = {}
        for m in self.models:
            assert issubclass(
                m, GenericModel
            ), f"""
                Pour utiliser la vue Omnibar la classe {m.get_id()} doit hériter de GenericModel'
            """
            key = m._meta.label
            items[key] = []
            cached = cache.get("omnibar:" + key)
            if not cached:
                cached = m.to_omnibar_dict()
                cache.set("omnibar:" + key, cached)
            items[key] = cached
        return JsonResponse(items, safe=False)


class GenericViewsetView(viewsets.ModelViewSet):
    queryset = None
    serializer_class = None
    model = None

    def get_queryset(self):
        return self.model.objects.all().order_by('-id')

    def get_serializer_class(self):
        if not self.serializer_class:
            serializer_class = GenericSerializer
            serializer_class.Meta.model = self.model
            self.serializer_class = serializer_class
        return self.serializer_class

    def list(self, request, format=None):
        # pas de cache si recherche
        qp = request.query_params
        if "search[value]" in qp and qp["search[value]"]:
            return super().list(request, format)

        if "start" not in qp or "length" not in qp:
            return super().list(request, format)

        key = f"{qp['start']}:{qp['length']}"
        cached = cache.get(self.model.__name__ + ":viewset:" + key)
        if not cached:
            cached = super().list(request, format).data
            cache.set(self.model.__name__ + ":viewset:" + key, cached)
        return Response(cached)

    class Meta:
        abstract = True


class GenericDatatableView(PermissionRequiredMixin, ListView):
    model: GenericModel
    template_name = "django_bkendoz/datatable_list.html"
    css_class = "datatable"
    css_modal_id = ""
    api_url: str

    def __init__(self, **kwargs):
        model_name = self.model.__name__

        #     assert globals().get(viewset), f'''
        # Erreur : impossible de créer la vue datatable pour le modèle {model_name} car aucun viewset {viewset} n'existe.
        #     '''

        self.current_app = self.model._meta.app_label
        self.permission_required = f"{self.current_app}.datatable_{model_name.lower()}"
        self.template_name = (
            self.model.get_view_data("datatable", "tpl") or self.template_name
        )

        reverse_url = f"{self.current_app}:{self.model.__name__.lower()}-viewset"
        self.api_url = self.model.get_view_data("datatable", "api_url") or reverse_lazy(
            reverse_url
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context["title"] = self.model.get_view_data("datatable", "title")
        context["menu"] = self.model.get_class_menu("datatable")
        context["css_class"] = self.model.get_view_data("datatable", "css_class") or self.css_class
        context["css_modal_id"] = self.model.get_view_data("datatable", "css_modal_id") or self.css_modal_id
        context["fields"] = self.model.get_view_data("datatable", "fields")
        context["api_url"] = self.api_url

        context["settings"] = settings
        context["layout_data"] = get_layout_data()
        return context


class GenericListView(PermissionRequiredMixin, ListView):
    template_name = "django_bkendoz/list.html"
    template_list_name = "django_bkendoz/table.html"
    list_cls = "generic-list"
    fields = "__all__"
    ordering = ["pk"]

    def __init__(self, **kwargs):
        assert hasattr(
            settings, "LIST_FIELDMAP"
        ), f"""
            Pas de template LIST_FIELDMAP défini dans settings.py,
            il faut définir comment chaque field de la liste va s'afficher dans un fichier de template .html
            """
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.list_{self.model.__name__.lower()}"
        )
        self.ordering = self.model.get_view_data("list", "ordering") or self.ordering
        self.template_name = (
            self.model.get_view_data("list", "tpl") or self.template_name
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context["list_title"] = self.model.get_view_data("list", "title")
        context["hide_search"] = (
            self.model.get_view_data("list", "hide_search") or False
        )
        context["list_menu"] = self.model.get_class_menu("list")
        context["list_cls"] = self.list_cls
        context["fields"] = self._get_fields()
        context["datatable_fields"] = self.model.get_view_data("viewset", "fields")
        context["api_url"] = f"api/{self.model.__name__.lower()}s/"
        context["html"] = (
            self.model.get_view_data("list", "html") or self.template_list_name
        )

        context["settings"] = settings
        context["layout_data"] = get_layout_data()
        return context

    def _get_fields(self):
        """Champs à afficher dans la vue en liste.

        Returns:
            str: Liste des champs
        """
        fields = self.model.get_view_data("list", "fields")
        return get_model_fields(self.model, fields)


class GenericCreateView(PermissionRequiredMixin, CreateView):
    template_name = "django_bkendoz/form_view.html"
    color_classes = []

    def __init__(self, **kwargs):
        assert hasattr(
            settings, "FORM_FIELDMAP"
        ), f"""
            Pas de template FORM_FIELDMAP défini dans settings.py,
            il faut définir dans ce fichier html comment chaque field
            particulier des formulaires vont s'afficher.
            """
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.add_{self.model.__name__.lower()}"
        )
        self.template_name = (
            self.model.get_view_data("create", "html") or self.template_name
        )

        if not self.form_class:
            self.form_class = self._create_generic_form()
            self.initial = {"model": self.model}
            # both fields and form_class not permitted
            self.fields = None
            # indent ? TODO
            super().__init__(**kwargs)

    def _create_generic_form(self):
        view_struct_fields = self.model.get_view_data("create")
        return get_generic_form(self.model, view_struct_fields)

    def form_valid(self, form):
        if hasattr(self.model, "history"):
            new_object = form.save()
            self.object = new_object
            new_object.history_create(
                self.request.user,
            )
            return redirect(self.get_success_url())
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        if "param0" in self.kwargs and "pk0" in self.kwargs:
            self.initial = {self.kwargs["param0"]: self.kwargs["pk0"]}
        if "param1" in self.kwargs and "pk1" in self.kwargs:
            self.initial = {
                self.kwargs["param0"]: self.kwargs["pk0"],
                self.kwargs["param1"]: self.kwargs["pk1"],
            }

        context = super().get_context_data(**kwargs)

        context["menu"] = self.model.get_class_menu("create")
        context["form_type"] = "create"
        context["form_title"] = self.model.get_view_data("create", "title")
        context["form_action"] = reverse_lazy(
            f"{self.current_app}:{self.model.__name__.lower()}-create"
        )
        if len(self.color_classes) > 0:
            context["color_palette"] = get_color_from_class(self.color_classes)

        context["layout_data"] = get_layout_data()
        context["settings"] = settings
        return context

    def get_success_url(self):
        self.absolute_success_url = self.model.get_view_data(
            "create", "absolute_success_url"
        )
        if self.absolute_success_url:
            return reverse_lazy(self.absolute_success_url)

        self.success_url = (
            get_href(self.model.get_view_data("create", "success_url"), self.object)
            or self.success_url
        )
        if self.success_url:
            return self.success_url

        for v, args in (("detail", [self.object.pk]), ("list", None), ("create", None)):
            if self.model.get_view_data(v):
                url = f"{self.current_app}:{self.model.__name__.lower()}-{v}"
                return reverse_lazy(url, args=args)


class GenericUpdateView(PermissionRequiredMixin, UpdateView):
    template_name = "django_bkendoz/form_view.html"
    color_classes = []

    def __init__(self, **kwargs):
        assert hasattr(
            settings, "FORM_FIELDMAP"
        ), f"""
            Pas de template FORM_FIELDMAP défini dans settings.py,
            il faut définir dans ce fichier html comment chaque field
            particulier des formulaires vont s'afficher.
            """
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.change_{self.model.__name__.lower()}"
        )
        self.template_name = (
            self.model.get_view_data("update", "html") or self.template_name
        )
        if not self.form_class:
            self.form_class = self._create_generic_form()
            # fields et form_class ne peuvent etre attribues en meme temps
            self.fields = None
            self.initial = {"model": self.model}
            super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["form_type"] = "update"
        context["form_title"] = self.model.get_view_data("update", "title")
        context["form_action"] = reverse_lazy(
            f"{self.current_app}:{self.model.__name__.lower()}-update",
            args=[self.object.pk],
        )
        if len(self.color_classes) > 0:
            context["color_palette"] = get_color_from_class(self.color_classes)

        context["menu"] = self.object.get_view_menu("update")
        context["settings"] = settings
        context["layout_data"] = get_layout_data()
        return context

    def form_valid(self, form):
        if hasattr(self.model, "history"):
            m2m_changes = self._compare_m2m_changes(form)
            self.object = form.save()
            self.object.history_update(self.request.user, m2m_changes)
            # form.save_m2m()
            return redirect(self.get_success_url())
        return super().form_valid(form)

    def get_success_url(self):
        self.success_url = (
            get_href(self.model.get_view_data("update", "success_url"), self.object)
            or self.success_url
        )
        if self.success_url:
            return self.success_url

        for v, args in (("detail", [self.object.pk]), ("list", None), ("create", None)):
            if self.model.get_view_data(v):
                url = f"{self.current_app}:{self.model.__name__.lower()}-{v}"
                return reverse_lazy(url, args=args)

    def _create_generic_form(self):
        view_struct_fields = self.model.get_view_data("update")
        return get_generic_form(self.model, view_struct_fields)

    def _compare_m2m_changes(self, form):
        m2m_changes = {}
        for f in self.model._meta.get_fields():
            if f.many_to_many and not isinstance(f, models.ManyToManyRel):
                m2m_changes[f.name] = {
                    "old": set(getattr(self.object, f.name).all()),
                    "new": set(form.cleaned_data[f.name]),
                }
                if m2m_changes[f.name]["old"] == m2m_changes[f.name]["new"]:
                    m2m_changes.pop(f.name)
        return m2m_changes


class GenericDetailView(PermissionRequiredMixin, DetailView):
    template_name = "django_bkendoz/detail.html"

    def __init__(self, **kwargs):
        assert hasattr(
            settings, "DETAIL_FIELDMAP"
        ), f"Pas de template DETAIL_FIELDMAP défini dans settings.py, il faut définir comment chaque field de la vue de détail va s'afficher dans un template"
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.detail_{self.model.__name__.lower()}"
        )
        self.template_name = (
            self.model.get_view_data("detail", "tpl") or self.template_name
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["detail_menu"] = self.object.get_view_menu("detail")
        context["fields"] = self._get_fields()
        context["html"] = self.model.get_view_data("detail", "html") or None
        context["settings"] = settings
        context["MEDIA_URL"] = settings.MEDIA_URL
        context["layout_data"] = get_layout_data()
        return context

    def _get_fields(self):
        fields = self.model.get_view_data("detail", "fields")
        if fields == "__all__":
            return None
        return fields


class GenericHistoryView(PermissionRequiredMixin, DetailView):
    template_name = "django_bkendoz/history.html"

    def __init__(self, **kwargs):
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.history_{self.model.__name__.lower()}"
        )
        self.template_name = (
            self.model.get_view_data("history", "tpl") or self.template_name
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["list_title"] = self.model.get_view_data("history", "title")
        context["history_menu"] = self.object.get_view_menu("history")
        context["fields"] = self._get_fields()
        context["html"] = self.model.get_view_data("history", "html") or None

        ct = ContentType.objects.get_for_model(self.object)
        context["history"] = get_global_history_model().objects.filter(
            record_model=ct,
            record_id=self.object.pk,
        )

        context["settings"] = settings
        context["layout_data"] = get_layout_data()
        return context

    def _get_fields(self):
        fields = self.model.get_view_data("history", "fields")
        if fields == "__all__":
            return None
        return fields


class GenericDeleteView(PermissionRequiredMixin, DeleteView):
    template_name = "django_bkendoz/delete.html"

    def __init__(self, **kwargs):
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.delete_{self.model.__name__.lower()}"
        )
        self.template_name = (
            self.model.get_view_data("delete", "tpl") or self.template_name
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["back_url"] = f"{self.current_app}:{self.model.__name__.lower()}-detail"
        context["html"] = self.model.get_view_data("delete", "html") or None
        context["settings"] = settings
        context["layout_data"] = get_layout_data()
        return context

    def delete(self, *args, **kwargs):
        if hasattr(self.model, "history"):
            self.object = self.get_object()
            self.object.history_delete(self.request.user)
        return super().delete(*args, **kwargs)

    def get_success_url(self):
        for v, args in (("list", None), ("create", None)):
            if self.model.get_view_data(v):
                url = f"{self.current_app}:{self.model.__name__.lower()}-{v}"
                return reverse_lazy(url, args=args)


class GenericExportxlsView(PermissionRequiredMixin, View):
    model = None

    def __init__(self, **kwargs):
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.exportxls_{self.model.__name__.lower()}"
        )
        super().__init__(**kwargs)

    def get(self, request, *args, **kwargs):
        if hasattr(self.model, "get_excel_dict"):
            xls_file = pyexcel.save_as(
                dest_file_type="xls", adict=self.model.get_excel_dict()
            )
            return FileResponse(
                xls_file,
                as_attachment=True,
                filename=f"{self.model.__name__.lower()}_export.xls",
            )
        else:
            tuple_fields = self.get_exportxls_fields()
            tuple_fields.reverse()
            if tuple_fields == "__all__":
                objects = self.model.objects.values()
            else:
                objects = self.model.objects.values(*tuple_fields)

            xls_file = pyexcel.save_as(dest_file_type="xls", records=objects)
            return FileResponse(
                xls_file,
                as_attachment=True,
                filename=f"{self.model.__name__.lower()}_export.xls",
            )

    def get_exportxls_fields(self):
        view_struct_fields = self.model.get_view_data("exportxls")
        return view_struct_fields


class GenericImportxlsView(PermissionRequiredMixin, FormView):
    template_name = "django_bkendoz/import_xls.html"
    form_class = ImportXlsForm
    model = None
    fields = []

    def __init__(self, **kwargs):
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.importxls_{self.model.__name__.lower()}"
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["form_title"] = f"Importer des données excel"
        context["form_subtitle"] = self.model._meta.verbose_name
        context["fields"] = self.get_import_fields()
        context["import_sample"] = self.model.get_samples()
        context["layout_data"] = get_layout_data()
        context["settings"] = settings
        return context

    def get_import_fields(self):
        view_struct_fields = self.model.get_view_data("importxls")
        return get_model_fields(self.model, view_struct_fields)

    def form_valid(self, form):
        xls_file = form.files["xls_file"]
        # print(pyexcel.get_sheet(file_type='xls', file_content=xls_file))
        records = pyexcel.get_records(file_type="xls", file_content=xls_file)

        context = self.get_context_data()
        # context['preview'] = True
        context["object_list"] = self.model.create_object_list_from_records(
            records, self.fields
        )
        # context['fields'] = get_model_fields(self.model, self.fields)
        # context['model_plural'] = self.model._meta.verbose_name_plural
        # context['form_action'] = f"{self.current_app}:{self.model.__name__.lower()}-importxlssave"
        return super().form_valid(form)
        # return render(self.request, self.template_name, context=context)

    def get_success_url(self):
        self.absolute_success_url = self.model.get_view_data(
            "importxls", "absolute_success_url"
        )
        if self.absolute_success_url:
            return reverse_lazy(self.absolute_success_url)

        for v, args in (("list", None), ("create", None)):
            if self.model.get_view_data(v):
                url = f"{self.current_app}:{self.model.__name__.lower()}-{v}"
                return reverse_lazy(url, args=args)


class GenericImportxlssaveView(PermissionRequiredMixin, View):
    model: GenericModel

    def post(self, request):
        for key, value in request.POST.items():
            if key.startswith("chk_"):
                if value == "off":
                    continue

                index = key.split("_")[1]
                data = json.loads(request.POST[index])
                m = self.model(**self.model.extract_json_dict(data))
                m.save()

        return redirect(
            reverse_lazy(f"{self.current_app}:{self.model.__name__.lower()}-list")
        )

    def __init__(self, **kwargs):
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.importxlssave_{self.model.__name__.lower()}"
        )
        super().__init__(**kwargs)


#   def form_valid(self, form):
#      def testinit(row):
#         # self.model.book_category.field.related_model
#         i = 0
#         new_row = []
#         for field_name in self.fields:
#            related_model = getattr(self.model, field_name).field.related_model
#            if related_model:
#               new_row.append(related_model.objects.get(pk=row[i]))
#            else:
#               new_row.append(row[i])
#            i = i + 1

#         print(new_row)
#         return new_row

#      xls_file = form.files['xls_file']
#      #print(pyexcel.get_sheet(file_type='xls', file_content=xls_file))
#      pyexcel.save_as(file_content=xls_file, file_type='xls',
#                            dest_initializer=testinit,
#                            dest_model=self.model,
#                       start_row=1,
#                       colnames=["book_category", "name"],
#                       dest_mapdict=["book_category", "name"]
#                      )

#      return super().form_valid(form)

#    def get_success_url(self):
#        if self.success_url:
#           return reverse_lazy(self.success_url)
#        else:
#           current_app = self.request.resolver_match.namespace
#           return reverse_lazy(f"{current_app}:{self.model.__name__.lower()}-importxls-preview")

#   def get(self, request, *args, **kwargs):
#      if self.fields == '__all__':
#         objects = self.model.objects.values()
#      else:
#         objects = self.model.objects.values(*self.fields)

#      xls_file = pyexcel.save_as(dest_file_type="xls", records=objects)
#      response = FileResponse(xls_file, as_attachment=True,
#                              filename=f"{self.model.__name__.lower()}_import.xls")
#      return response
#      # return HttpResponse(xls_file, content_type="application/vnd.ms-excel")
#   pass


class GenericLoginView(auth_views.LoginView):
    extra_context = {"settings": settings, "test": "test"}


class GenericLogoutView(auth_views.LogoutView):
    extra_context = {"settings": settings, "test": "test"}


class GenericProfileView(PermissionRequiredMixin, UpdateView):
    template_name = "auth/user_detail.html"
    model = get_user_model()
    # fields = ["first_name", "last_name", "email", "style"]
    fields = ["first_name", "last_name", "email"]
    extra_context = {
        "settings": settings,
    }

    def __init__(self, **kwargs):
        self.current_app = self.model._meta.app_label
        self.permission_required = (
            f"{self.current_app}.detail_{self.model.__name__.lower()}"
        )
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["settings"] = settings
        context["layout_data"] = get_layout_data()
        context["history"] = get_global_history_model().objects.filter(user=self.object)
        return context


class UserRecordView(APIView):
    """
    API View to create or get a list of all the registered
    users. GET request returns the registered users whereas
    a POST request allows to create a new user.
    """

    permission_classes = [IsAdminUser]

    def get(self, format=None):
        users = get_user_model().objects.all()
        serializer = GenericUserSerializer(users, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = GenericUserSerializer(data=request.data)
        if serializer.is_valid(raise_exception=ValueError):
            serializer.create(validated_data=request.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED)

        return Response(
            {
                "error": True,
                "error_msg": serializer.error_messages,
            },
            status=status.HTTP_400_BAD_REQUEST,
        )


def create_model_paths(model):
    mod_name = model.__name__
    mod_name_low = mod_name.lower()
    path_to_return = []

    def get_fields(view):
        fields = model.get_view_data(view.lower())
        if fields == "__all__":
            return get_model_fields(model)
        else:
            return fields
        if view == "Exportxls":
            return get_model_fields(model, fields)

    assert issubclass(
        model, GenericModel
    ), f"""
        {model} doit hériter de GenericModel pour pouvoir créer la structure de vues"""

    for view in model.get_views_struct().keys():
        view = view.title()
        assert globals().get(
            f"Generic" + view + "View"
        ), f"""
    Erreur : aucune vue {view} définit dans la structure de vues pour Generic{view}View pour le modèle {model}.
        """

        ClassView = type(
            # name
            mod_name + view + "View",
            # subclasses
            (globals()["Generic" + view + "View"],),
            # attr
            {"model": model, "fields": get_fields(view)},
        )

        if view == "Viewset":
            path_to_return.append(
                path(
                    "datatables/" + mod_name_low + "s",
                    ClassView.as_view({"get": "list"}),
                    name=mod_name_low + "-" + view.lower(),
                )
            )

        else:

            view_path = mod_name_low + "s/" + view.lower()
            if view in ["Update", "Detail", "Delete", "History"]:
                view_path += "/<int:pk>"

            path_to_return.append(
                path(
                    view_path,
                    ClassView.as_view(),
                    name=mod_name_low + "-" + view.lower(),
                )
            )

            if view == "Create":
                view_path += "/<str:param0>/<int:pk0>"
                view_path1 = view_path + "/<str:param1>/<int:pk1>"
                path_to_return.append(
                    path(
                        view_path,
                        ClassView.as_view(),
                        name=mod_name_low + "-" + view.lower(),
                    )
                )

                path_to_return.append(
                    path(
                        view_path1,
                        ClassView.as_view(),
                        name=mod_name_low + "-" + view.lower(),
                    )
                )

    return path_to_return
