from rest_framework.generics import (ListAPIView, CreateAPIView, UpdateAPIView, RetrieveAPIView, DestroyAPIView)
from rest_framework.response import Response
from rest_framework.filters import SearchFilter, OrderingFilter

from django.db import transaction

from django.shortcuts import get_object_or_404

from datetime import datetime

from apps.consultant.serialziers.consultant_serializers import ConsultantDeleteAPISerializer, ConsultantListAPISerializer, ConsultantStoreAPISerializer
from apps.consultant.models import Consultant
from apps.consultant.services.consultant_services import save_consultant



class ConsultantListAPIView(ListAPIView):
    serializer_class = ConsultantListAPISerializer
    filter_backends = [SearchFilter, OrderingFilter]
    ordering_fields = ['id', 'name', 'type', 'phone_no', 'created_by', 'email', 'note']
    search_fields = ['id', 'name', 'type__name', 'phone_no', 'created_by__first_name', 'created_by__last_name', 'email', 'note']

    def get_queryset(self):
        consultant_without_project_id = self.request.query_params.get('consultant_without_project_id')
        project_id = self.request.query_params.get('project_id')
        with_trashed = self.request.query_params.get('with_trashed')
        queryset = Consultant.objects.all()

        if with_trashed == 'true':
            queryset = Consultant.objects.with_trashed()

        if consultant_without_project_id:
            queryset = queryset.exclude(project_consultants__id=consultant_without_project_id)
        elif project_id:
            queryset = queryset.filter(project_consultants__id=project_id)

        return queryset


class ConsultantCreateAPIView(CreateAPIView):
    serializer_class = ConsultantStoreAPISerializer

    @transaction.atomic
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        validated_data = serializer.validated_data
        validated_data['created_by']= self.request.user

        consultant = save_consultant(validated_data)

        serializer = self.serializer_class(instance=consultant)

        return Response(serializer.data)


class ConsultantEditAPIView(UpdateAPIView):
    http_method_names = ['patch']
    serializer_class = ConsultantStoreAPISerializer

    def patch(self, request, pk, *args, **kwargs):
        consultant = get_object_or_404(Consultant, pk=pk)

        serializer = self.serializer_class(instance=consultant, data=request.data)
        serializer.is_valid(raise_exception=True)

        consultant = save_consultant(serializer.validated_data, id=consultant.id)

        serializer = self.serializer_class(instance=consultant)

        return Response(serializer.data)


class ConsultantDeleteAPIView(DestroyAPIView):
    serializer_class = ConsultantDeleteAPISerializer

    def delete(self, request, pk, *args, **kwargs):
        consultant = get_object_or_404(Consultant, pk=pk)

        Consultant.objects.filter(id=pk).update(deleted_by=self.request.user, deleted_at=datetime.now())

        serializer = self.serializer_class(consultant)

        return Response(serializer.data)


class ConsultantDetailAPIView(RetrieveAPIView):
    serializer_class = ConsultantListAPISerializer
    queryset = Consultant.objects.with_trashed().select_related('type')