import datetime

from django.db.models import Prefetch, Q, Sum, F
from django.http import QueryDict
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets
from oauth2_provider.contrib.rest_framework import (
    TokenHasReadWriteScope,
)
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import AllowAny

from ticket.helper import send_image_to_server
from authentication.helper.refresh import refresh
from authentication.models import SystemUserProfile
from panel.KillHouse.helpers import get_difference_carcasses_percent
from panel.ReportingPanel.filterset import ProfileFilterSet, ManagementVetFarmFilterSet, PoultryFilterSet
from panel.VetFarm.serializers import VetFarmSerializer, VetFarmInspectionSerializer, ManagementVetFarmSerializer, \
    PoultryForCityVetSerializer, VetForSubSectorSerializer, VetForSubSectorTransactionSerializer
from rest_framework.response import Response
from rest_framework import status
import string
import random
import os

ARVAN_Vet_Farm_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/'
# ARVAN_Vet_Farm_URL = 'https://vet-farm.s3.ir-thr-at1.arvanstorage.ir/'

from panel.models import VetFarm, Poultry, PoultryHatching, Vet, VetFarmInspection, PoultryRequest, KillHouseRequest, \
    PercentageOfWageType, WageType, KillHouse, SubSectorTransactions, BarDifferenceRequest


# ویوست مربوط به ثبت و نمایش و ... دامپزشک فارم
class VetFarmViewSet(viewsets.ModelViewSet):
    queryset = VetFarm.objects.all()
    permission_classes = [TokenHasReadWriteScope]
    serializer_class = VetFarmSerializer

    def create(self, request, *args, **kwargs):
        # refresh(request.user.id)

        user = SystemUserProfile.objects.get(user=request.user)
        if 'vet_key' in request.data.keys():
            vet = Vet.objects.get(key=request.data['vet_key'])
            request.data.pop('vet_key')
        else:
            vet = Vet.objects.get(user=user)
        poultry = Poultry.objects.get(key=request.data['poultry_key'])
        request.data.pop('poultry_key')
        halls = request.data['halls']
        request.data.pop('halls')
        # vet_farm = VetFarm.objects.filter(poultry=poultry, hall=int(request.data['hall']))
        # if vet_farm.count() > 0:
        #     vet_farm = vet_farm.last()
        #     if vet_farm.vet.id == vet.id:
        #         return Response({"result": "object exist"}, status=status.HTTP_403_FORBIDDEN)
        #     else:
        #         pass
        for hall in halls:
            vet_farm = VetFarm(
                vet=vet,
                poultry=poultry,
                hall=int(hall),
            )
            vet_farm.save()
        return Response({"result": "created"}, status=status.HTTP_201_CREATED)

        # serializer = self.serializer_class(data=request.data)
        # if serializer.is_valid():
        #     vetfarm = serializer.create(validated_data=request.data)
        #     vetfarm.vet = vet
        #     vetfarm.poultry = poultry
        #     vetfarm.save()
        #     return Response(serializer.data, status=status.HTTP_201_CREATED)
        # return Response(serializer.errors)

    # تابع مربوط به نمایش دوره جوجه ریزی مرغدار
    def list(self, request, *args, **kwargs):
        # refresh(request.user.id)
        # list of self poultry houses
        user = SystemUserProfile.objects.get(user=request.user)
        vet = Vet.objects.get(user=user)
        vet_farm = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry', 'vet')
        serializer = VetFarmSerializer(vet_farm, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def destroy(self, request, pk=None, *args, **kwargs):
        # refresh(request.user.id)
        try:
            vet_farm = VetFarm.objects.get(key=request.GET["vet_farm_key"])
            # if VetFarmInspection.objects.filter(vet_farm=vet_farm).exists():
            #     return Response({"result": "object can not delete"}, status=status.HTTP_403_FORBIDDEN)
            vet_farm.trash = True
            vet_farm.save()
            return Response({"result": "object deleted"}, status=status.HTTP_200_OK)
        except:
            return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_403_FORBIDDEN)


class TotalVetSubSectorWageDashboardViewSet(viewsets.ModelViewSet):
    queryset = Vet.objects.all()
    permission_classes = [TokenHasReadWriteScope]
    serializer_class = VetForSubSectorSerializer

    def list(self, request, *args, **kwargs):

        total_quantity = 0
        total_weight = 0
        total_wage = 0
        total_wage_type = WageType.objects.filter(trash=False)
        province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount
        free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount
        out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province',
                                                                 trash=False).first().amount

        percentages_wage_type = PercentageOfWageType.objects.filter(trash=False)
        other_province_kill_request_percent = percentages_wage_type.filter(
            wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100
        other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell',
                                                                         share_type__en_name='other').first().percent / 100

        other_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province',
                                                                         share_type__en_name='other').first().percent / 100
        other_province_kill_request_amount = province_live_wage_amount * other_province_kill_request_percent
        other_free_sell_carcasses_amount = free_sell_carcasses_wage_amount * other_free_sell_carcasses_percent

        other_out_poultry_request_amount = out_poultry_request_wage_amount * other_out_poultry_request_percent

        kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id')
        if 'date1' in request.GET:
            date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date()
            date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date()
            poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'),
                                                             province_state__in=('pending', 'accepted'), out=True,
                                                             out_province_request_cancel=False, temporary_trash=False,
                                                             wage_pay=True, has_wage=True,
                                                             temporary_deleted=False, vet_farm__isnull=False,
                                                         send_date__date__gte=date1,
                                                         send_date__date__lte=date2
                                                             )
            kill_house_requests = KillHouseRequest.objects.filter(
                Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q(
                    Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q(
                    Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False,
                province_request__poultry_request__vet_farm__isnull=False,
                # clearance_code__isnull=False,
                clearance_code__isnull=False,
                trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1,
            kill_request__recive_date__date__lte=date2
            )
            vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False, date__date__gte=date1,
                                                           date__date__lte=date2)
            difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False,
                                                                      state='accepted',acceptor_date__date__gte=date1,
                                                                  acceptor_date__date__lte=date2)
        else:
            poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'),
                                                             province_state__in=('pending', 'accepted'), out=True,
                                                             out_province_request_cancel=False, temporary_trash=False,
                                                             wage_pay=True, has_wage=True,
                                                             temporary_deleted=False, vet_farm__isnull=False,
                                                             )
            kill_house_requests = KillHouseRequest.objects.filter(
                Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q(
                    Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q(
                    Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False,
                province_request__poultry_request__vet_farm__isnull=False,
                # clearance_code__isnull=False,
                clearance_code__isnull=False,
                trash=False, calculate_status=True
            )
            difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False,
                                                                      state='accepted')
            vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False)
        # quarantine_code__isnull=False)
        out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[
                                                    'total'] or 0
        out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[
                                                  'total'] or 0



        province_live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0
        province_live_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[
                                     'total'] or 0

        province_live_weight += \
            difference_requests.aggregate(total=Sum('weight'))['total'] or 0
        total_quantity += province_live_quantity + out_province_poultry_request_quantity
        total_weight += province_live_weight + out_province_poultry_request_weight

        province_carcasses_weight = province_live_weight * 0.75
        if 'date1' in request.GET:
            internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent(date1,date2)
        else:
            internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent()

        external_pure_province_carcasses_weight = province_carcasses_weight - internal_pure_province_carcasses_weight

        total_pure_internal_province_carcasses_amount = internal_pure_province_carcasses_weight * other_province_kill_request_amount
        total_pure_external_province_carcasses_amount = external_pure_province_carcasses_weight * other_free_sell_carcasses_amount
        out_province_poultry_request_amount = out_province_poultry_request_weight * other_out_poultry_request_amount


        vet_deposit_amount = vet_deposit.aggregate(total=Sum('amount'))['total'] or 0
        total_wage += total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount
        total_remain_wage = total_wage - vet_deposit_amount

        result = {
            "total_quantity": total_quantity,
            "total_weight": total_weight,
            "out_province_poultry_request_quantity": out_province_poultry_request_quantity,
            "out_province_poultry_request_weight": out_province_poultry_request_weight,
            "province_live_quantity": province_live_quantity,
            "province_live_weight": province_live_weight,
            "province_carcasses_weight": province_carcasses_weight,
            "internal_pure_province_carcasses_weight": internal_pure_province_carcasses_weight,
            "external_pure_province_carcasses_weight": external_pure_province_carcasses_weight,
            "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount,
            "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount,
            "out_province_poultry_request_amount": out_province_poultry_request_amount,
            "total_wage": total_wage,
            "number_of_deposit": len(vet_deposit),
            "vet_deposit_amount": vet_deposit_amount,
            "total_remain_wage": total_remain_wage,
        }

        return Response(result, status=status.HTTP_200_OK)


class VetForSubSectorViewSet(viewsets.ModelViewSet):
    queryset = Vet.objects.all()
    permission_classes = [TokenHasReadWriteScope]
    serializer_class = VetForSubSectorSerializer

    # تابع مربوط به نمایش دوره جوجه ریزی مرغدار
    def list(self, request, *args, **kwargs):
        vet = Vet.objects.filter(pk__in=VetFarm.objects.all().values_list('vet', flat=True), trash=False).order_by('id')
        serializer = self.serializer_class(vet, many=True,context={'request':request})
        return Response(serializer.data, status=status.HTTP_200_OK)

    def destroy(self, request, pk=None, *args, **kwargs):
        # refresh(request.user.id)
        try:
            vet_farm = VetFarm.objects.get(key=request.GET["vet_farm_key"])
            # if VetFarmInspection.objects.filter(vet_farm=vet_farm).exists():
            #     return Response({"result": "object can not delete"}, status=status.HTTP_403_FORBIDDEN)
            vet_farm.trash = True
            vet_farm.save()
            return Response({"result": "object deleted"}, status=status.HTTP_200_OK)
        except:
            return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_403_FORBIDDEN)


class VetForSubSectorTransactionViewSet(viewsets.ModelViewSet):
    queryset = Vet.objects.all()
    permission_classes = [TokenHasReadWriteScope]
    serializer_class = VetForSubSectorTransactionSerializer

    def list(self, request, *args, **kwargs):
        vet = Vet.objects.filter(pk__in=VetFarm.objects.all().values_list('vet', flat=True), trash=False).order_by('id')
        serializer = self.serializer_class(vet, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


# ویوست مربوط به ثبت و نمایش و ... دامپزشک فارم
class VetFarmInspectionViewSet(viewsets.ModelViewSet):
    queryset = VetFarmInspection.objects.all()
    permission_classes = [TokenHasReadWriteScope]
    serializer_class = VetFarmInspectionSerializer

    def create(self, request, *args, **kwargs):
        # refresh(request.user.id)
        user = SystemUserProfile.objects.get(user=request.user)
        vet = Vet.objects.get(user=user)
        image_list = []
        vet_farm = VetFarm.objects.get(key=request.data['key'])
        request.data.pop('key')
        try:
            poultry_hatching = PoultryHatching.objects.get(key=request.data['poultry_hatching_key'])
            request.data.pop('poultry_hatching_key')
        except:
            poultry_hatching = None
        try:
            images = request.data['image']
            request.data.pop('image')
        except:
            images = None
        if poultry_hatching != None:
            if PoultryRequest.objects.filter(hatching=poultry_hatching, hatching__left_over=0,
                                             hatching__allow_hatching='pending', hatching__state='pending').exists():
                return Response({"result": "باقی مانده موجود در سالن صفر میباشد."},
                                status=status.HTTP_406_NOT_ACCEPTABLE)
        today = datetime.datetime.now().date()
        inspections = VetFarmInspection.objects.filter(vet_farm__vet=vet, state='pending', create_date__year=today.year,
                                                       create_date__month=today.month, create_date__day=today.day)
        if inspections.count() > 0:
            inspection = inspections.last()
            if poultry_hatching != None:
                if inspection.poultry_hatching.poultry.id != poultry_hatching.poultry.id:
                    return Response({"result": "can not register"}, status=status.HTTP_403_FORBIDDEN)
                elif inspection.poultry_hatching.poultry.id == poultry_hatching.poultry.id and inspection.poultry_hatching.hall == int(
                        request.data['hall']):
                    return Response({"result": "can not register"}, status=status.HTTP_400_BAD_REQUEST)
            elif poultry_hatching == None:
                if inspection.vet_farm.poultry != vet_farm.poultry:
                    return Response({"result": "can not register"}, status=status.HTTP_403_FORBIDDEN)
                elif inspection.vet_farm.hall == int(request.data['hall']):
                    return Response({"result": "can not register"}, status=status.HTTP_400_BAD_REQUEST)

            #
            # else:
            #     for inspect in inspections:
            #         if inspect.hall == int(request.data['hall']):
            #             return Response({"result": "can not register"}, status=status.HTTP_403_FORBIDDEN)
            #         else:
            #             pass

        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            vet_farm_inspection = serializer.create(validated_data=request.data)
            vet_farm_inspection.vet_farm = vet_farm
            if images != None:
                for image in images:
                    image_list.append(send_image_to_server(image))

                vet_farm_inspection.image = image_list
            if poultry_hatching != None:
                if int(vet_farm_inspection.Losses) > 0:
                    vet_farm.vetfarm_losses += int(vet_farm_inspection.Losses)
                    vet_farm.save()
                    if poultry_hatching.losses != 0:
                        poultry_hatching.losses = poultry_hatching.losses + int(vet_farm_inspection.Losses)
                        poultry_hatching.left_over = poultry_hatching.left_over - int(vet_farm_inspection.Losses)
                    else:
                        poultry_hatching.losses = vet_farm_inspection.Losses
                        poultry_hatching.left_over = poultry_hatching.quantity - int(vet_farm_inspection.Losses)
                    poultry_hatching.save()
                vet_farm_inspection.poultry_hatching = poultry_hatching
            vet_farm_inspection.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors)

    def list(self, request, *args, **kwargs):
        # refresh(request.user.id)
        if 'key' in request.GET:
            vet_farm_inspection = VetFarmInspection.objects.filter(vet_farm__key=request.GET['key'])
            serializer = VetFarmInspectionSerializer(vet_farm_inspection, many=True)
        elif 'poultry_key' in request.GET:
            if 'hall' in request.GET:
                vet_farm_inspection = VetFarmInspection.objects.filter(
                    vet_farm__poultry__key=request.GET['poultry_key'], hall=int(request.GET['hall']))
                if vet_farm_inspection.count() == 0:
                    vet_farm_inspection = []
                serializer = VetFarmInspectionSerializer(vet_farm_inspection, many=True)

        else:
            user = SystemUserProfile.objects.get(user=request.user)
            vet = Vet.objects.get(userprofile=user)
            vet_farm_inspection = VetFarmInspection.objects.filter(vet_farm__vet=vet)
            serializer = VetFarmInspectionSerializer(vet_farm_inspection, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class CustomPagination(PageNumberPagination):
    page_size = 10


class ManagementVetFarmViewSet(viewsets.ModelViewSet):
    queryset = VetFarm.objects.all()
    permission_classes = [AllowAny]
    serializer_class = ManagementVetFarmSerializer
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend]
    filterset_class = ManagementVetFarmFilterSet
    poultry_filterset_class = PoultryFilterSet
    filterset_fields = [
        'poultry__user__mobile',
        'poultry__unit_name',
        'poultry__address__city__name',

    ]
    poultry_filterset_fields = [
        'user__mobile',
        'unit_name',
        'address__city__name',

    ]

    def list(self, request, *args, **kwargs):
        user = SystemUserProfile.objects.get(user=request.user)
        if request.GET['role'] == 'VetFarm':
            vet = Vet.objects.get(user=user)
            vet_farm = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry', 'vet')
            vet_farm_list = []
            if 'search' in request.GET:
                if request.GET['search'] == 'filter':
                    if request.GET['value'] != "" and request.GET['value'] != 'undefined':
                        for item in self.filterset_fields:
                            query = QueryDict('{0}__contains={1}'.format(item, request.GET['value']))
                            if (self.filterset_class(
                                    data=query,
                                    queryset=vet_farm
                            )
                            ).filter():
                                ps = self.filterset_class(data=query, queryset=vet_farm)
                                vet_farm_list = ps.filter()
                        vet_farm = [] if len(vet_farm_list) == 0 else vet_farm_list
            page_size = request.query_params.get('page_size', None)

            if page_size:
                self.pagination_class.page_size = int(page_size)

            page = self.paginate_queryset(vet_farm)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)

            serializer = ManagementVetFarmSerializer(vet_farm, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

        else:
            poultries = Poultry.objects.filter(
                pk__in=PoultryHatching.objects.filter(trash=False, allow_hatching='pending', state='pending',
                                                      archive=False).values_list('poultry__id', flat=True),
                address__city=user.city)
            poultries_list = []
            if 'search' in request.GET:
                if request.GET['search'] == 'filter':
                    if request.GET['value'] != "" and request.GET['value'] != 'undefined':
                        for item in self.poultry_filterset_fields:
                            query = QueryDict('{0}__contains={1}'.format(item, request.GET['value']))
                            if (self.poultry_filterset_class(
                                    data=query,
                                    queryset=poultries
                            )
                            ).filter():
                                ps = self.filterset_class(data=query, queryset=poultries)
                                poultries_list = ps.filter()
                        poultries = [] if len(poultries_list) == 0 else poultries_list
            page_size = request.query_params.get('page_size', None)

            if page_size:
                self.pagination_class.page_size = int(page_size)

            page = self.paginate_queryset(poultries)
            if page is not None:
                serializer = PoultryForCityVetSerializer(page, many=True)
                return self.get_paginated_response(serializer.data)

            serializer = PoultryForCityVetSerializer(poultries, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
