from django.views.decorators.csrf import csrf_exempt
from django.db.models.query_utils import Q
from rest_framework import viewsets
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import action
from rest_framework.exceptions import MethodNotAllowed
from .response import MangeAPIResponse
from core.utils.excel import export_excel


class TemplateHTMLRendererView(APIView):
    renderer_classes = [TemplateHTMLRenderer]

    def get(self, request):
        return Response()

    def post(self, request):
        raise MethodNotAllowed(method='post')


class ManageResponseView(APIView):
    def get(self, request):
        raise MethodNotAllowed(method='get')

    def post(self, request):
        raise MethodNotAllowed(method='post')


class ManageResponseViewSet(viewsets.GenericViewSet):
    model = None
    instance = None
    manage = None


class ManageListView(object):
    def get_query_set(self, request):
        if not self.filter_cls:
            return self.queryset
        return self.filter_cls(request.GET, self.queryset).qs

    @action(methods=['get'], detail=False)
    def search(self, request, **kwargs):
        extra_filter = kwargs.get('extra_filter', Q())
        order_by = '-%s' % getattr(self, 'pk_name', 'id')
        if getattr(self, 'order_by', None):
            order_by = self.order_by
        if extra_filter != Q():
            query_set = self.get_query_set(request).filter(extra_filter).order_by(order_by)
        else:
            query_set = self.get_query_set(request).order_by(order_by)
        page = self.paginate_queryset(query_set)
        serializers = self.get_serializer(page, many=True)
        return self.get_paginated_response(data=serializers.data)


class ManageAddView(object):
    @action(methods=['post'], detail=False)
    def add(self, request, **kwargs):
        add_serializer_class = getattr(self, 'add_serializer_class', self.serializer_class)
        serializer = add_serializer_class(data=request.data, context={'request': request, 'created': True})
        serializer.is_valid(raise_exception=True)
        serializer.save(**serializer.validated_data)
        return MangeAPIResponse(data=serializer.data)


class ManageDetailView(object):
    @action(methods=['get'], detail=False)
    def details(self, request, **kwargs):
        instance = self.instance
        if not instance:
            pk = request.GET.get('id', request.data.get('id'))
            if getattr(self, 'is_unique_id', False):
                instance = self.model.objects.get(unique_id=pk)
            else:
                instance = self.model.objects.get(pk=pk)
        detail_serializer_class = getattr(self, 'detail_serializer_class', self.serializer_class)
        serializer = detail_serializer_class(instance=instance, context={'request': request})
        return MangeAPIResponse(data=serializer.data)


class ManageEditView(object):
    @action(methods=['post'], detail=False)
    def edit(self, request, **kwargs):
        instance = self.instance
        if not instance:
            pk = request.GET.get('id', request.data.get('id'))
            if getattr(self, 'is_unique_id', False):
                instance = self.model.objects.get(unique_id=pk)
            else:
                instance = self.model.objects.get(pk=pk)
        edit_serializer_class = getattr(self, 'edit_serializer_class', self.serializer_class)
        serializer = edit_serializer_class(instance=instance, data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        serializer.save(**serializer.validated_data)
        return MangeAPIResponse(data=serializer.data)


class ManageDeleteView(object):
    @action(methods=['post'], detail=False)
    def delete(self, request, **kwargs):
        instance = self.instance
        if not instance:
            pk = request.GET.get('id')
            if getattr(self, 'is_unique_id', False):
                instance = self.model.objects.get(unique_id=pk)
            else:
                instance = self.model.objects.get(pk=pk)
        field_names = [f.name for f in self.model._meta.fields]
        if 'deleted' in field_names:
            instance.deleted = True
            instance.save(update_fields=['deleted'])
        else:
            self.model.objects.filter(pk=instance.pk).delete()
        return MangeAPIResponse()


class ManageActiveView(object):
    @action(methods=['post'], detail=False)
    def ban(self, request, **kwargs):
        instance = self.instance
        if not instance:
            pk = request.GET.get('id')
            if getattr(self, 'is_unique_id', False):
                instance = self.model.objects.get(unique_id=pk)
            else:
                instance = self.model.objects.get(pk=pk)
        instance.active = False
        instance.save(update_fields=['active'])
        return MangeAPIResponse()

    @action(methods=['post'], detail=False)
    def reset(self, request, **kwargs):
        instance = self.instance
        if not instance:
            pk = request.GET.get('id')
            if getattr(self, 'is_unique_id', False):
                instance = self.model.objects.get(unique_id=pk)
            else:
                instance = self.model.objects.get(pk=pk)
        instance.active = True
        instance.save(update_fields=['active'])
        return MangeAPIResponse()


class ManageExportView(object):
    @action(methods=['get'], detail=False)
    def export(self, request, **kwargs):
        export_conf = kwargs.get('export_conf', {})
        return export_excel(self.get_query_set(request).order_by('-id'),
                            export_conf)
