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.contractor.serializers.contractor_serializers import ContractorListAPISerializer, ContractorDeleteAPISerializer, ContractorStoreAPISerializer
from apps.contractor.models import Contractor
from apps.contractor.services.contractor_services import save_contractor



class ContractorListAPIView(ListAPIView):
    serializer_class = ContractorListAPISerializer
    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):
        contractor_without_project_id = self.request.query_params.get('contractor_without_project_id')
        project_id = self.request.query_params.get('project_id')
        with_trashed = self.request.query_params.get('with_trashed')
        queryset = Contractor.objects.all()

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

        if contractor_without_project_id:
            queryset = queryset.exclude(project_contractors__id=contractor_without_project_id)
        elif project_id:
            queryset = queryset.filter(project_contractors__id=project_id)

        return queryset


class ContractorCreateAPIView(CreateAPIView):
    serializer_class = ContractorStoreAPISerializer

    @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

        contractor = save_contractor(validated_data)

        serializer = self.serializer_class(instance=contractor)

        return Response(serializer.data)


class ContractorEditAPIView(UpdateAPIView):
    http_method_names = ['patch']
    serializer_class = ContractorStoreAPISerializer

    def patch(self, request, pk, *args, **kwargs):
        contractor = get_object_or_404(Contractor, pk=pk)

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

        contractor = save_contractor(serializer.validated_data, id=contractor.id)

        serializer = self.serializer_class(instance=contractor)

        return Response(serializer.data)


class ContractorDeleteAPIView(DestroyAPIView):
    serializer_class = ContractorDeleteAPISerializer

    def delete(self, request, pk, *args, **kwargs):
        contractor = get_object_or_404(Contractor, pk=pk)

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

        serializer = self.serializer_class(contractor)

        return Response(serializer.data)


class ContractorDetailAPIView(RetrieveAPIView):
    serializer_class = ContractorListAPISerializer
    queryset = Contractor.objects.with_trashed().select_related('type')