from app.entities import enums
from django.db import transaction
from rest_framework import viewsets, status
from rest_framework.response import Response
from app.applicationlayer.utils import model_to_dict
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters import rest_framework as filters
from app.entities.models import Delegation, Department
from app.applicationlayer.utils import (
    CustomPagination, status_message_response, log_save
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.delegation import serializer
from app.applicationlayer.management.delegation.table_filters import DelegationFilterSet
from app.helper import decorators


class DelegationViewSet(viewsets.ModelViewSet):
    queryset = Delegation.objects.all().order_by('-created')
    serializer_class = serializer.DelegationSerializer
    pagination_class = CustomPagination
    lookup_field = 'code'
    filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
    filterset_class = DelegationFilterSet
    ordering_fields = '__all__'
    search_fields = ('name')

    @transaction.atomic
    def create(self, request, *args, **kwargs):

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)

        message = status_message_response(
            201, 'success',
            'New Delegation created', serializer.data
        )

        return Response(
            message
        )

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        
        page = self.paginate_queryset(queryset)

        if page is not None:
            serializer = self.get_serializer(page, many=True)

            message = status_message_response(
                200,
                'success',
                'list of Delegation found',
                serializer.data
            )
            return self.get_paginated_response(message)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @decorators.error_safe
    @transaction.atomic
    def destroy(self, request, *args, **kwargs):

        message = {
            'code': 400,
            'status': 'failed',
            'message': 'Delegation/s cannot delete, Please update instead'
        }
        return Response(message, status=status.HTTP_400_BAD_REQUEST)

    @transaction.atomic
    def update(self, request, *args, **kwargs):

        partial = kwargs.pop('partial', True)
        instance = self.get_object()
        serializer = self.get_serializer(
            instance,
            data=request.data,
            partial=partial)
        serializer.is_valid(raise_exception=True)

        old_instance = model_to_dict(instance)
        
        if not (old_instance['name'].lower() == 'vendor/implementor' or
                old_instance['name'].lower() == 'requestor'):
            
            self.perform_update(serializer)
            new_instance = serializer.data

            log_save(
                enums.LogEnum.UPDATE.value,
                enums.LogEntitiesEnum.DELEGATION.value,
                old_instance['id'],
                old_instance,
                new_instance
            )

            return Response(serializer.data)
        
        else:
            message = {
                'code': 400,
                'status': 'failed',
                'message': 'Default delegation cannot edit'
            }
            return Response(message, status=status.HTTP_400_BAD_REQUEST)

