import datetime
import threading
from datetime import timedelta
from django.shortcuts import get_object_or_404, redirect

import jdatetime
from django.http import HttpResponse
from rest_framework import viewsets
from oauth2_provider.contrib.rest_framework import (
    TokenHasReadWriteScope,
    OAuth2Authentication,
)
from oauth2_provider.models import AccessToken
from rest_framework.pagination import PageNumberPagination

from general_urls import CLIENT_ID, CLIENT_SECRET, BASE_URL
from panel.ReportingPanel.filterset import ProfileFilterSet
from panel.admin import PROJECT_API_KEY
from panel.filterset import WagePaymentFilterSet
from panel.models import WareHouseFactor, InspectorOperator, KillHouseVet, Itransaction, Wallet, KillHousePercentage, \
    Jahad, Admin, VetSupervisor, ProvincialGovernment, CityJahad, ProvinceAllowKillHouseChooseStewardGuilds, \
    ProvinceAllowPoultryChooseKillHouse, Pricing, Guilds, POSMachine, PosVersion, PosItem, POSId, UserLoginLog, \
    ProvinceAllowKillHouseDirectBuying
from ticket.helper import send_image_to_server
from .filterset import UserProfileFilterSet, SystemUserProfileFilteSet, ExternalTransactionFilterSet
from .helper.refresh import refresh
from .sahandsms.sms import (
    send_sms,
    send_otp_code,
    send_password
)
from .serializer.serializer import (
    AddressSerializer,
    UserProfileSerializer,
    BankCardSerializer,
    SystemUserProfileSerializer, SystemUserProfileForAllUsersSerializer, SystemUserProfileBaseInfoSerializer,
    ExternalTransactionSerializer,
    # SystemUserProfileInfoSerializer
)
from .serializers import SystemAddressSerializer, CityForProductPricingSerializer
from panel.CityOperator.serializers import CityOperatorSerializer, CityOperatorForAllUserSerializer
from panel.ProvinceOperator.serializers import ProvinceOperatorSerializer, InspectorOperatorSerializer, JahadSerializer, \
    AdminSerializer, VetSupervisorSerializer, ProvincialGovernmentSerializer, ProvinceOperatorForAllUserSerializer, \
    InspectorOperatorForAllUserSerializer, JahadForAllUserSerializer, AdminForAllUserSerializer, \
    VetSupervisorForAllUserSerializer, ProvincialGovernmentForAllUserSerializer, CityJahadForAllUserSerializer, \
    PricingSerializer, GeneralGuildsSerializer
from panel.poultry.serializers import (
    PoultrySerializer,
    PoultryTenantSerializer, PoultryForAllUserSerializer
)
from panel.KillHouse.serializers import (
    KillHouseOperatorSerializer,
    VetSerializer, KillHouseSerializer, KillHouseVetSerializer, KillHouseDriverSerializer,
    KillHouseOperatorForAllUserSerializer, VetForAllUserSerializer, KillHouseDriverForAllUserSerializer,
    KillHouseVetForAllUserSerializer, KillHouseForAllUserSerializer
)
from rest_framework.permissions import (
    AllowAny,
    IsAuthenticated,
    DjangoModelPermissions
)
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import permission_classes, api_view
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.decorators import authentication_classes
from rest_framework.authentication import get_authorization_header
from django.core.cache.backends.base import DEFAULT_TIMEOUT
from authentication.models import CityUnit, ExternalTransaction
from django.contrib.auth.hashers import make_password
from django.contrib.auth.views import LoginView
from panel.helper import (
    create_except_profile,
    update_except_profile,
    remove_null_fields, operator_update_except_profile
)
from authentication.models import (
    UserProfile,
    Address,
    BankCard,
    SystemUserProfile,
    SystemAddress,
    City,
    Province
)
from panel.models import (
    Poultry,
    ProvinceOperator,
    CityOperator,
    KillHouseOperator,
    Vet,
    KillHouseDriver,
    KillHouseADDCAR,
    PoultryTenant,
    KillHouse,

)
from rest_framework.response import Response
from django.contrib.auth.models import User, Group
from django.core.cache import cache
from django.conf import settings
from rest_framework import status
from oauth2_provider.models import AccessToken
from .helper.image_services import (
    upload_image,
    upload_listed_image
)
from django.http.response import JsonResponse, HttpResponseRedirect
import requests
import json
import random
import uuid
from django.contrib.auth.views import LoginView
from django.contrib.auth.hashers import make_password
import cryptocode
import string
import random
import os
from django_filters.rest_framework import DjangoFilterBackend
from django.http import QueryDict
import xlsxwriter
from io import StringIO, BytesIO

# آدرس پایه برای ارسال در خواست ثبت نام به سیستم پایه شرکت آرتا
from .serializers import SystemAddressSerializer, CityUnitSerializer, CitySerializer, ProvinceSerializer

ARTA_URL_REGISTER = "https://userbackend.rasadyar.com/api/register/"
# آدرس پایه برای ارسال در خواست ورود به سیستم پایه شرکت آرتا
ARTA_URL_LOGIN = "https://userbackend.rasadyar.com/api/login/"
# آدرس پایه برای سیستم ورود و ثبت نام بر اساس توکن
ARTA_URL_CHANGE_MOBILE_NUMBER = "https://userbackend.rasadyar.com/change_mobile_number/"
CACHE_TTL = getattr(settings, "CACHE_TTL", DEFAULT_TIMEOUT)
# آدرس پایه برای ذخیره تصویر کاربر در استوریج آروان
ARVAN_User_Image_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/'
# ARVAN_User_Image_URL = 'http://user-image-gallery.s3.ir-thr-at1.arvanstorage.ir/'

ARTA_URL_SEND_OTP = "https://userbackend.rasadyar.com/api/send_otp/"
ARTA_URL_CHECK_OTP = "https://userbackend.rasadyar.com/api/check_otp/"
ARTA_URL_CHANGE_PASSWORD = "https://userbackend.rasadyar.com/api/change_password/"


class CustomPagination(PageNumberPagination):
    page_size = 10


class ExternalTransactionViewSet(viewsets.ModelViewSet):
    queryset = ExternalTransaction.objects.all()
    serializer_class = ExternalTransactionSerializer
    permission_classes = [TokenHasReadWriteScope]
    filter_backends = [DjangoFilterBackend]
    pagination_class = CustomPagination
    filterset_class = ExternalTransactionFilterSet
    filterset_fields = [
        'saleReferenceId',
        'refId',
        'orderId',
        'cardHolderPan',

    ]

    def list(self, request, *args, **kwargs):
        user = SystemUserProfile.objects.get(user=request.user)
        date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date()
        date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date()
        transactions_list = []
        if request.GET['role'] == 'KillHouse':

            if request.GET['state'] == 'failed':
                if 'type' in request.GET:
                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        kill_house_user=user,
                        status='failed',
                        transaction_type='wallet',

                        trash=False).order_by('id')
                else:
                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        kill_house_user=user,
                        status='failed',
                        transaction_type='wage-gateway',

                        trash=False).order_by('id')
            else:
                if 'type' in request.GET:
                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        kill_house_user=user,
                        status='completed',
                        transaction_type='wallet',
                        trash=False).order_by('id')
                else:

                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        kill_house_user=user,
                        status='completed',
                        transaction_type='wage-gateway',
                        trash=False).order_by('id')
        else:

            if request.GET['state'] == 'failed':
                if 'type' in request.GET:
                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        status='failed',
                        transaction_type='wallet',
                        trash=False).order_by('id')
                else:
                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        status='failed',
                        transaction_type='wage-gateway',
                        trash=False).order_by('id')
            else:
                if 'type' in request.GET:
                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        status='completed',
                        transaction_type='wallet',
                        trash=False).order_by('id')
                else:

                    transactions = ExternalTransaction.objects.filter(
                        date__date__gte=date1,
                        date__date__lte=date2,
                        status='completed',
                        transaction_type='wage-gateway',
                        trash=False).order_by('id')

        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=transactions
                        )
                        ).filter():
                            ps = self.filterset_class(data=query, queryset=transactions)
                            transactions_list = ps.filter()
                    transactions = [] if len(transactions_list) == 0 else transactions_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(transactions)
        if page is not None:
            serializer = ExternalTransactionSerializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = ExternalTransactionSerializer(transactions, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


# ویوست مربوط به استان
class ProvinceViewSet(viewsets.ModelViewSet):
    queryset = Province.objects.all()
    serializer_class = ProvinceSerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        # refresh(request.user.id)
        user = SystemUserProfile.objects.get(user=request.user)
        province = Province.objects.filter(key=user.province.key)
        serializer = CitySerializer(province, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


# ویوست مربوط به شهرستان
class CityViewSet(viewsets.ModelViewSet):
    queryset = City.objects.all()
    serializer_class = CitySerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        refresh(request.user.id)
        city = City.objects.filter(
            province=Province.objects.get(key=request.GET['province_key'])
            # province=Province.objects.get(key='1e364f53-f873-4af9-9e93-7e4816e889ae')
        )
        serializer = CitySerializer(city, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class CityForProducctPricingViewSet(viewsets.ModelViewSet):
    queryset = City.objects.all()
    serializer_class = CityForProductPricingSerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        user = SystemUserProfile.objects.get(user=request.user)
        city = City.objects.filter(trash=False, province=user.province).order_by('id')
        serializer = self.serializer_class(city, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def update(self, request, pk=None, *args, **kwargs):
        city = City.objects.get(trash=False, key=request.data['city_key'])
        request.data.pop('city_key')
        serializer = self.serializer_class(city)
        serializer.update(instance=city, validated_data=request.data)
        return Response(serializer.data, status=status.HTTP_200_OK)


class CityWithOutProvinceKeyViewSet(viewsets.ModelViewSet):
    queryset = City.objects.all()
    serializer_class = CitySerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        # refresh(request.user.id)
        user = SystemUserProfile.objects.get(user=request.user)
        city = City.objects.filter(
            province=Province.objects.get(key=user.province.key)
        )
        serializer = CitySerializer(city, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


class CitysViewSet(viewsets.ModelViewSet):
    queryset = City.objects.all()
    serializer_class = CitySerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        # refresh(request.user.id)
        user = SystemUserProfile.objects.get(user=request.user)
        city = City.objects.filter(
            province=Province.objects.get(key=user.province.key)
        ).exclude(name='فاقد شهرستان')
        serializer = CitySerializer(city, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)


# ویوست مربوط به زیربخش شهرستان
class CityUnitViewSet(viewsets.ModelViewSet):
    queryset = CityUnit.objects.all()
    serializer_class = CityUnitSerializer
    permission_classes = [TokenHasReadWriteScope]


# ویوست مربوط به آدرس
class SystemAddressViewSet(viewsets.ModelViewSet):
    queryset = SystemAddress.objects.all()
    serializer_class = SystemAddressSerializer
    permission_classes = [TokenHasReadWriteScope]


# ویوست مربوط به جستجو اطلاعات کاربر یا کاربران
class UserProfileSearchViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer
    permission_classes = [TokenHasReadWriteScope]
    filter_backends = [DjangoFilterBackend]
    filterset_class = UserProfileFilterSet
    filterset_fields = [
        'fullname',
        'mobile',
        'first_name',
        'last_name',
        'breeding_unique_id',
        'address__city',
        'address__province',
        'role__name',
    ]

    def list(self, request, *args, **kwargs):
        if 'type' in request.GET:
            if request.GET['type'] == 'filter':
                for item in self.filterset_fields:
                    query = QueryDict('{0}__contains={1}'.format(item, request.GET['value']))
                    if (self.filterset_class(
                            data=query,
                            queryset=self.queryset
                    )
                    ).filter():
                        ps = self.filterset_class(data=query, queryset=self.queryset)
                        filtered_user = ps.filter()
                        serializer = self.serializer_class(filtered_user, many=True)
                        return Response(serializer.data)
            return Response({"msg": "Enter 'Type' In Get Parameters"}, status=status.HTTP_403_FORBIDDEN)
        else:
            queryset = self.queryset.all()
            serializer = UserProfileSerializer(queryset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)


# ویوست مربوط به پروفایل کاربری که شامل ساخت و ویرایش و حذف
class UserProfileViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer
    permission_classes = [TokenHasReadWriteScope]

    # تابع مربوط به ثبت پروفایل کاربر
    def create(self, request, *args, **kwargs):
        role = Group.objects.get(name__exact=request.data['role'])
        request.data.pop('role')
        city = request.data['city']
        province = request.data['province']
        address = request.data['address']
        try:
            image = request.data['image']
            request.data.pop('image')
        except:
            image = ""

        request.data.pop('city')
        request.data.pop('province')
        request.data.pop('address')
        mobile = request.data['mobile']
        if UserProfile.objects.filter(mobile=mobile):
            return Response('user already exist')
        index = UserProfile.objects.all().last().base_order
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            user_profile = serializer.create(validated_data=request.data)
            user_profile.image = send_image_to_server(image)
            password = str(random.randint(10000, 99000))

            user = User(
                first_name=user_profile.fullname,
                username=user_profile.mobile,
                password=cryptocode.encrypt(password, password)
            )
            user.save()
            user_address = Address(
                city=city,
                province=province,
                address=address,
            )
            user_address.save()
            user_profile.user = user
            user_profile.role = role
            user_profile.address = user_address
            user_profile.base_order = index + 1
            user_profile.fullname = user_profile.first_name + " " + user_profile.last_name
            user_profile.save()
            send_password(user_profile.mobile, password)

            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors)

    # تابع مربوط به نمایش اطلاعات پروفایل کاربر
    def list(self, request, *args, **kwargs):
        if 'type' in request.GET:
            if request.GET['type'] == 'operator':
                queryset = self.queryset.filter(role__name__exact="Poultry")
                serializer = UserProfileSerializer(queryset, many=True)
                return Response(serializer.data, status=status.HTTP_200_OK)
            if request.GET['type'] == 'user':
                queryset = UserProfile.objects.all().filter(user__exact=request.user)
                serializer = UserProfileSerializer(queryset, many=True)
                return Response(serializer.data, status=status.HTTP_200_OK)
        return Response({'Msg': 'Enter type parameter in url'})

    # تابع مربوط به ویرایش اطلاعات پروفایل کاربر
    def update(self, request, pk=None, *args, **kwargs):
        try:
            if request.data['image'] == "":
                user_image = None

            else:
                user_image = request.data['image']
                request.data.pop('image')

        except:
            user_image = None

        try:
            role = request.data['role']
            request.data.pop('role')

        except:
            role = None

        try:
            city = request.data['city']
            request.data.pop('city')

        except:
            city = None

        try:
            province = request.data['province']
            request.data.pop('province')

        except:
            province = None

        try:
            address = request.data['address']
            request.data.pop('address')

        except:
            address = None

        queryset = UserProfile.objects.get(key=request.data["key"])
        user_address = Address.objects.get(id=queryset.address.id)
        request.data.pop('key')
        if user_image:
            queryset.image = send_image_to_server(user_image)
        if role:
            queryset.role = Group.objects.get(name__exact=role)
        if city:
            user_address.city = city
        if province:
            user_address.province = province
        if address:
            user_address.address = address
        user_address.save()
        queryset.save()
        serializer = self.serializer_class(queryset)
        serializer.update(instance=queryset, validated_data=request.data)
        return Response(serializer.data, status=status.HTTP_200_OK)

    # تابع مربوط به حذف اطلاعات پروفایل کاربر
    def destroy(self, request, pk=None, *args, **kwargs):
        user_profile = UserProfile.objects.get(key__exact=request.GET["key"])
        user = User.objects.get(id=user_profile.user.id)
        address = Address.objects.get(id=user_profile.address.id)
        user_profile.delete()
        user.delete()
        address.delete()
        return Response('user deleted', status=status.HTTP_200_OK)


class ForceDiagramViewSet(viewsets.ModelViewSet):
    queryset = SystemUserProfile.objects.all()
    serializer_class = SystemUserProfileSerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        refresh(request.user.id)
        user = SystemUserProfile.objects.get(user=request.user)

        if 'role' in request.GET:
            role = request.GET['role'].split(',')
            new_persons = []

            persons = SystemUserProfile.objects.filter(role__name__in=role, province=user.province).order_by('id')
            if persons.count() > 0:
                for person in persons:
                    if person in new_persons:
                        pass
                    else:
                        new_persons.append(person)
            serializer = SystemUserProfileSerializer(new_persons, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

        if 'all' in request.GET:
            poultry = Poultry.objects.filter(user__province=user.province)
            city_operator = CityOperator.objects.filter(user__province=user.province)
            province_operator = ProvinceOperator.objects.filter(user__province=user.province,
                                                                user__role__name='ProvinceOperator')
            financial_operator = Poultry.objects.filter(user__province=user.province,
                                                        user__role__name='ProvinceFinancial')
            inspector_operator = InspectorOperator.objects.filter(user__province=user.province)
            killhouse_operator = KillHouseOperator.objects.filter(user__province=user.province)
            driver = KillHouseDriver.objects.filter(user__province=user.province)
            vet = Vet.objects.filter(user__province=user.province)
            killhouse_vet = KillHouseVet.objects.filter(vet__user__province=user.province)
            diageram_dict = {
                "poultry": poultry.count(),
                "city_operator": city_operator.count(),
                "province_operator": province_operator.count(),
                "financial_operator": financial_operator.count(),
                "inspector_operator": inspector_operator.count(),
                "killhouse_operator": killhouse_operator.count(),
                "driver": driver.count(),
                "vet": vet.count(),
                "killhouse_vet": killhouse_vet.count(),
            }

            return Response(diageram_dict, status=status.HTTP_200_OK)
        elif 'Poultry' in request.GET:
            poultry = Poultry.objects.filter(address__province=user.province)
            serializer = PoultrySerializer(poultry, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        elif 'CityOperator' in request.GET:
            cityoperator = CityOperator.objects.filter(address__province=user.province)
            serializer = CityOperatorSerializer(cityoperator, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        elif 'ProvinceOperator' in request.GET:
            operator = SystemUserProfile.objects.filter(role__name='ProvinceOperator',
                                                        province=user.province)
            provinceoperator = ProvinceOperator.objects.filter(user=operator.last())
            serializer = ProvinceOperatorSerializer(provinceoperator, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

        elif 'ProvinceFinancial' in request.GET:
            operator = SystemUserProfile.objects.filter(role__name='ProvinceFinancial',
                                                        province=user.province)
            provincefinancial = ProvinceOperator.objects.filter(user=operator.last())

            serializer = ProvinceOperatorSerializer(provincefinancial, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        elif 'ProvinceInspector' in request.GET:
            provinceinspector = InspectorOperator.objects.filter(address__province=user.province)
            serializer = InspectorOperatorSerializer(provinceinspector, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        elif 'KillHouse' in request.GET:
            killhouse = KillHouse.objects.filter(system_address__province=user.province)
            serializer = KillHouseSerializer(killhouse, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        elif 'KillHouseVet' in request.GET:
            killhousevet = KillHouseVet.objects.filter(kill_house__system_address__province=user.province)
            serializer = KillHouseVetSerializer(killhousevet, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

        # elif 'VetFarm' in request.GET:
        #
        #     vetfarm = SystemUserProfile.objects.filter(role__name='VetFarm',
        #                                                province=user.province)
        #     serializer = self.serializer_class(vetfarm, many=True)
        #     return Response(serializer.data, status=status.HTTP_200_OK)
        elif 'Driver' in request.GET:

            driver = KillHouseDriver.objects.filter(address_province=user.province)
            serializer = KillHouseDriverSerializer(driver, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)


class TotalSystemUserProfileStatisticsDashboardViewSet(viewsets.ModelViewSet):
    queryset = SystemUserProfile.objects.all()
    serializer_class = SystemUserProfileSerializer
    permission_classes = [AllowAny]

    def list(self, request, *args, **kwargs):
        users = SystemUserProfile.objects.filter().only('user_id')
        guilds = Guilds.objects.filter(trash=False)
        poultrys = Poultry.objects.filter(trash=False).only('user_id')
        price = Pricing.objects.filter(trash=False).last()

        if 'role' in request.GET:
            if request.GET['role'] == 'CityOperator':
                user = SystemUserProfile.objects.get(user=request.user)
                city_operator = CityOperator.objects.get(trash=False, user=user)
                poultries = poultrys.filter(city_operator=city_operator.unit_name)
            elif request.GET['role'] in ['CityJahad', 'CityPoultry']:
                user = SystemUserProfile.objects.get(user=request.user)
                poultries = poultrys.filter(address__city=user.city)
            else:
                poultries = poultrys
        else:
            poultries = poultrys
        return Response({
            "users": users.count(),
            "poultries": poultries.count(),
            "guilds": guilds.count(),
        })


class TotalPricingStatisticsDashboardViewSet(viewsets.ModelViewSet):
    queryset = Pricing.objects.all()
    serializer_class = PricingSerializer
    permission_classes = [AllowAny]

    def list(self, request, *args, **kwargs):
        price = Pricing.objects.filter(trash=False).last()

        return Response(
            {"last_price": price.live_chicken_price, "last_change": str(price.modify_date.date())}
        )


class ShowSystemUserProfileViewSet(viewsets.ModelViewSet):
    queryset = SystemUserProfile.objects.all()
    serializer_class = SystemUserProfileSerializer
    permission_classes = [TokenHasReadWriteScope]

    # تابع مربوط به نمایش اطلاعات پروفایل کاربر
    def list(self, request, *args, **kwargs):
        refresh(request.user.id)
        if 'role' in request.GET:
            queryset = self.queryset.filter(role__name__exact=request.GET['role'])
            if queryset.count() > 0:
                serializer = UserProfileSerializer(queryset, many=True)
                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response([], status=status.HTTP_200_OK)
        else:
            users_info = []
            for user in SystemUserProfile.objects.all().exclude(role__isnull=True):
                city = user.city.name if user.city != None else None
                province = user.province.name if user.province != None else None
                for role in user.role.all():
                    if role.name == 'KillHouse':
                        oprator = KillHouseOperator.objects.get(user=user)
                        kill_house_wallet = oprator.wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=kill_house_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount

                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "national_id": user.national_id,
                            "wallet_key": oprator.wallet.key,
                            "inventory": oprator.wallet.inventory,
                            "city": city,
                            "province": province,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)

                    elif role.name == 'Poultry':
                        poultry_wallet = Poultry.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=poultry_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount
                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": poultry_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)
                    elif role.name == 'CityOperator':

                        city_wallet = CityOperator.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=city_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount
                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": city_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "depositable": (creditor + deposit) - (debtor + penalty)
                        }
                        users_info.append(internal_dict)
                    elif role.name == 'ProvinceOperator':
                        province_wallet = ProvinceOperator.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=province_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount

                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": province_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)
                    elif role.name == 'ProvinceInspector':
                        inspector_wallet = InspectorOperator.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=inspector_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount
                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": inspector_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)
                    elif role.name == 'ProvinceFinancial':
                        financial_wallet = ProvinceOperator.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=financial_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount
                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": financial_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)
                    elif role.name == 'Driver':

                        driver_wallet = KillHouseDriver.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=driver_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount
                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": driver_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)
                    elif role.name == 'KillHouseVet':
                        kill_house_vet_wallet = Vet.objects.get(user=user).wallet
                        creditor = 0
                        debtor = 0
                        penalty = 0
                        deposit = 0
                        for i in Itransaction.objects.filter(wallet=kill_house_vet_wallet):
                            if i.transaction_type == 'creditor':
                                creditor += i.transfer_amount
                            elif i.transaction_type == 'debtor':
                                debtor += i.transfer_amount
                            elif i.transaction_type == 'penalty':
                                penalty += i.transfer_amount
                            elif i.transaction_type == 'deposit':
                                deposit += i.transfer_amount
                        internal_dict = {
                            "base_orde": user.base_order,
                            "fullname": user.fullname,
                            "id": user.id,
                            "role": role.name,
                            "mobile": user.mobile,
                            "wallet_key": kill_house_vet_wallet.key,
                            "national_id": user.national_id,
                            "province": province,
                            "city": city,
                            "creditor": creditor,
                            "debtor": debtor,
                            "penalty": penalty,
                            "deposit": deposit,
                            "depositable": (creditor + deposit) - (debtor + penalty)

                        }
                        users_info.append(internal_dict)
            return Response(users_info, status=status.HTTP_200_OK)


# class StandardResultsSetPagination(PageNumberPagination):
#     page_size = 2
#     page_size_query_param = 'page_size'
#     max_page_size = 1000


object_classes_total = {
    'Poultry': Poultry,
    'CityOperator': CityOperator,
    'ProvinceOperator': ProvinceOperator,
    'KillHouse': KillHouse,
    'ProvinceInspector': InspectorOperator,
    'ProvinceFinancial': ProvinceOperator,
    'Vet': Vet,
    'Jahad': Jahad,
    'CityJahad': CityJahad,
    'Driver': KillHouseDriver,
    'Admin': Admin,
    'VetFarm': Vet,
    'KillHouseVet': KillHouseVet,
    'VetSupervisor': VetSupervisor,
    'ProvincialGovernment': ProvincialGovernment,
}
serializer_object_classes_total = {

    'Poultry': PoultryForAllUserSerializer,
    'CityOperator': CityOperatorForAllUserSerializer,
    'ProvinceOperator': ProvinceOperatorForAllUserSerializer,
    'KillHouse': KillHouseForAllUserSerializer,
    # 'KillHouse': KillHouseOperatorForAllUserSerializer,
    'ProvinceInspector': InspectorOperatorForAllUserSerializer,
    'ProvinceFinancial': ProvinceOperatorForAllUserSerializer,
    'Vet': VetForAllUserSerializer,
    'Jahad': JahadForAllUserSerializer,
    'CityJahad': CityJahadForAllUserSerializer,
    'Driver': KillHouseDriverForAllUserSerializer,
    'Admin': AdminForAllUserSerializer,
    'VetFarm': VetForAllUserSerializer,
    'KillHouseVet': KillHouseVetForAllUserSerializer,
    'VetSupervisor': VetSupervisorForAllUserSerializer,
    'ProvincialGovernment': ProvincialGovernmentForAllUserSerializer,
}


def get_data_list(user):
    data_list = []
    for item in user.role.all():
        object_class = object_classes_total.get(item.name)
        serializer = serializer_object_classes_total.get(item.name)
        if object_class and serializer:
            if item.name == 'KillHouseVet':
                query = object_class.objects.filter(vet__user=user)
            elif item.name == 'KillHouse':
                query = object_class.objects.filter(kill_house_operator__user=user)
            else:
                query = object_class.objects.filter(user=user)
            if query.exists():
                for queries in query:
                    data_list.append({
                        "role_name": item.name,
                        "details": serializer(queries).data
                    })
    return data_list


class SystemUserProfileViewSet(viewsets.ModelViewSet):
    queryset = SystemUserProfile.objects.all()
    serializer_class = SystemUserProfileSerializer
    permission_classes = [AllowAny]
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend]
    filterset_class = ProfileFilterSet
    filterset_fields = [
        'base_order',
        'mobile',
        'fullname',
        'first_name',
        'last_name',
        'city__name',

    ]

    object_classes = {
        'Poultry': Poultry,
        'CityOperator': CityOperator,
        'ProvinceOperator': ProvinceOperator,
        'KillHouse': KillHouseOperator,
        'ProvinceInspector': InspectorOperator,
        'ProvinceFinancial': ProvinceOperator,
        'Vet': Vet,
        'Jahad': ProvinceOperator,
        'Driver': KillHouseDriver,
        'PoultryTenant': PoultryTenant,
        'VetFarm': Vet,
        'Guilds': Guilds,
        'Steward': Guilds,
        'KillHouseVet': KillHouseVet
    }
    serializer_object_classes = {
        'Poultry': PoultrySerializer,
        'CityOperator': CityOperatorSerializer,
        'ProvinceOperator': ProvinceOperatorSerializer,
        'Guilds': GeneralGuildsSerializer,
        'Steward': GeneralGuildsSerializer,
        'KillHouse': KillHouseOperatorSerializer,
        'ProvinceInspector': InspectorOperatorSerializer,
        'ProvinceFinancial': ProvinceOperatorSerializer,
        'Vet': VetSerializer,
        'Jahad': ProvinceOperatorSerializer,
        'Driver': KillHouseDriverSerializer,
        # 'PoultryTenant': PoultryTenant,
        'VetFarm': VetSerializer,
        'KillHouseVet': KillHouseVetSerializer
    }

    def list(self, request, *args, **kwargs):
        user = SystemUserProfile.objects.get(user=request.user, trash=False)

        if 'self-profile' in request.GET:
            userprofile = SystemUserProfile.objects.get(user=request.user)
            serializer = self.serializer_class(userprofile)
            return Response(serializer.data, status=status.HTTP_200_OK)

        elif 'city_users' in request.GET:
            out_list = []  # contains out put list
            users = []

            city_operator = CityOperator.objects.get(user=SystemUserProfile.objects.get(user=request.user))
            city = city_operator.address.city
            city_unit_list = []
            city_units = CityUnit.objects.filter(city=city)
            for city in city_units:
                city_unit_list.append(city.name)

            for u in SystemUserProfile.objects.filter(role__name='Poultry', city__name__in=city_unit_list):
                users.append(u)
            for user_without_role in SystemUserProfile.objects.filter(city__name__in=city_unit_list):
                if len(user_without_role.role.all()) == 0:
                    users.append(user_without_role)
            for user in users:
                out_list.append({'profile': self.serializer_class(user).data})
            return Response(out_list, status=status.HTTP_200_OK)
        elif 'users_info' in request.GET:
            # inspector = InspectorOperator.objects.get(user=SystemUserProfile.objects.get(user=request.user))
            user = SystemUserProfile.objects.get(user=request.user, trash=False)
            userprofile_list = []
            province = user.province
            out_put = []  # contains out put list
            role = request.GET['roles'].split(',') if request.GET['roles'] != "" else None
            if role != None:
                userprofile = SystemUserProfile.objects.filter(role__name__in=role, province=province, trash=False)
            else:
                userprofile = SystemUserProfile.objects.filter(province=province, trash=False).exclude(
                    role__name='SuperAdmin')  # contains userprofile object
            if 'search' in request.GET:
                if request.GET['search'] == 'filter':
                    if request.GET['value'] != "":
                        for item in self.filterset_fields:
                            query = QueryDict('{0}__contains={1}'.format(item, request.GET['value']))
                            if (self.filterset_class(
                                    data=query,
                                    queryset=userprofile
                            )
                            ).filter():
                                ps = self.filterset_class(data=query, queryset=userprofile)
                                userprofile_list = ps.filter()
                        userprofile = [] if len(userprofile_list) == 0 else userprofile_list
                # if request.GET['search'] == 'filter':
                #     if request.GET['value'] != "":
                #         for item in self.filterset_fields:
                #             query = QueryDict('{0}__contains={1}'.format(item, request.GET['value']))
                #             if (self.filterset_class(
                #                     data=query,
                #                     queryset=userprofile
                #             )
                #             ).filter():
                #                 ps = self.filterset_class(data=query, queryset=userprofile)
                #                 userprofile_list = ps.filter()
                #         userprofile = [] if len(userprofile_list) == 0 else userprofile_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(userprofile)
            if page is not None:
                serializer = self.serializer_class(page, many=True)
                return self.get_paginated_response(serializer.data)

            serializer = self.serializer_class(userprofile, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
            # for user in userprofile:
            #     out_put.append({'profile': self.serializer_class(user).data})
            # return Response(out_put, status=status.HTTP_200_OK)

        elif 'users_base_info' in request.GET:
            users = SystemUserProfile.objects.filter(province=user.province, trash=False)
            serializer_base_info = SystemUserProfileBaseInfoSerializer(users, many=True)
            return Response(serializer_base_info.data, status=status.HTTP_200_OK)

        elif 'all_users' in request.GET:
            user = self.queryset.get(key=request.GET['userprofile_key'])
            data_list = get_data_list(user)
            return Response(data_list, status=status.HTTP_200_OK)
        # return super().list(request, *args, **kwargs)

        # if 'page' in request.GET:
        # end = int(request.GET['page']) * 3
        # start = end - 3

    def retrieve(self, request, *args, **kwargs):
        refresh(request.user.id)
        user = self.queryset.get(key=request.GET['userprofile_key'])  # contains user profile object

        data_list = []  # contains list of roles data
        role_list = []  # contains list of roles names

        # iterate in user roles
        if user.role is not None:
            for item in user.role.all():
                if item.name == 'Admin':
                    continue
                object_class = self.object_classes[item.name]  # contains related class object to role
                if item.name == 'KillHouseVet':
                    if object_class.objects.filter(vet__user=user).exists():
                        query = object_class.objects.filter(vet__user=user)  # contains query objects
                        for queries in query:
                            serializer = self.serializer_object_classes[
                                item.name]  # contains related serializer to role
                            data_list.append({item.name: serializer(queries).data})
                        role_list.append(item.name)

                else:
                    if object_class.objects.filter(user=user).exists():
                        query = object_class.objects.filter(user=user)  # contains query objects
                        for queries in query:
                            serializer = self.serializer_object_classes[
                                item.name]  # contains related serializer to role
                            data_list.append({item.name: serializer(queries).data})
                        role_list.append(item.name)

            serializer = self.serializer_class(user)

            return Response({
                'profile': serializer.data,
                'roles_data': data_list,
                'roles_list': role_list
            },
                status=status.HTTP_200_OK
            )

        # if user does not exists
        else:
            return Response(status=status.HTTP_409_CONFLICT)

    def create(self, request, *args, **kwargs):
        refresh(request.user.id)
        if 'userprofile_key' in request.data.keys():
            person = SystemUserProfile.objects.get(key=request.data['userprofile_key'])
        else:
            person = None

        edit_type = request.data['type']
        request.data.pop('type')

        if edit_type == 'check_user':
            # if user exists in system
            if self.queryset.filter(
                    mobile=request.data['value']
            ).exists() or self.queryset.filter(
                national_id=request.data['value']
            ).exists() or self.queryset.filter(
                base_order=request.data['value']
            ).exists():

                if self.queryset.filter(
                        mobile=request.data['value']
                ).exists():
                    # contains user object
                    user = self.queryset.get(
                        mobile=request.data['value'],
                    )

                if self.queryset.filter(
                        national_id=request.data['value']
                ).exists():
                    # contains user object
                    user = self.queryset.get(
                        national_id=request.data['value'],
                    )
                if self.queryset.filter(
                        base_order=request.data['value']
                ).exists():
                    # contains user object
                    user = self.queryset.get(
                        base_order=request.data['value'],
                    )

                data_list = []  # contains list of roles data
                role_list = []  # contains list of roles names

                # iterate in user roles
                if user.role is not None:
                    for item in user.role.all():
                        if item.name == 'Admin':
                            continue
                        object_class = self.object_classes[item.name]  # contains related class object to role
                        if item.name == 'KillHouseVet':
                            if object_class.objects.filter(vet__user=user).exists():
                                query = object_class.objects.filter(vet__user=user)  # contains query objects
                                for queries in query:
                                    serializer = self.serializer_object_classes[
                                        item.name]  # contains related serializer to role
                                    data_list.append({item.name: serializer(queries).data})
                                role_list.append(item.name)
                        else:
                            if object_class.objects.filter(user=user).exists():
                                query = object_class.objects.filter(user=user)  # contains query objects
                                for queries in query:
                                    serializer = self.serializer_object_classes[
                                        item.name]  # contains related serializer to role
                                    data_list.append({item.name: serializer(queries).data})
                                role_list.append(item.name)

                serializer = self.serializer_class(user)

                return Response({
                    'profile': serializer.data,
                    'roles_data': data_list,
                    'roles_list': role_list
                },
                    status=status.HTTP_200_OK
                )

            # if user does not exists
            else:
                url = 'https://userbackend.rasadyar.com/user_identity/'
                # url = 'https://artasystemback.sstit.ir/user_identity/'
                headers = {
                    "Authorization": str(request.headers['Authorization']),
                    "Content-Type": "application/json"
                }
                request.data['type'] = edit_type

                req = requests.post(
                    url=url,
                    data=json.dumps(request.data),
                    headers=headers,
                    verify=False
                )
                if req.status_code == 200:
                    return Response(req.json(), status=status.HTTP_200_OK)
                else:
                    return Response(status=status.HTTP_409_CONFLICT)
        if edit_type == 'profile':

            # create user object
            if not User.objects.filter(username=request.data['mobile']).exists():
                user = User(username=request.data['mobile'])
            else:
                return Response({"result": "کاربر قبلا ثیت شده است !"}, status=status.HTTP_403_FORBIDDEN)

            # register user to base system
            data = {
                "username": request.data['mobile'],
                "password": request.data['password'],
                "first_name": request.data['first_name'],
                "last_name": request.data['last_name'],
                "national_code": request.data['national_code'],
                "api_key": PROJECT_API_KEY,
            }
            req = requests.post(
                url=ARTA_URL_REGISTER,
                data=data,
                verify=False
            )
            if req.status_code == 200:
                # set password for user by admin
                if request.data['password'] != "":
                    password = request.data['password']
                    user.password = cryptocode.encrypt(password, password)
                    user.save()

                # get city object
                city = City.objects.get(
                    key=request.data['city']
                )
                request.data.pop('city')

                # get province object
                province = Province.objects.get(
                    key=request.data['province']
                )
                request.data.pop('province')

                # upload user image
                req = upload_image(req=request, field='image')

                # send request data to serializer
                serializer = self.serializer_class(data=req.data)
                base_order = SystemUserProfile.objects.all()
                if base_order.count():
                    base_order = base_order.last().base_order + 1
                else:
                    base_order = 1000
                if serializer.is_valid():
                    userprofile_object = serializer.create(validated_data=req.data)
                    userprofile_object.city = city
                    userprofile_object.province = province
                    userprofile_object.user = user
                    userprofile_object.password = password
                    userprofile_object.base_order = base_order
                    userprofile_object.save()
                    serializer = self.serializer_class(userprofile_object)
                    return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response({"result": "کاربر قبلا ثیت شده است !"}, status=status.HTTP_400_BAD_REQUEST)
        if edit_type == "Poultry":
            # poultry owner object
            user = self.queryset.get(key=request.data['owner_key'])

            for poultry_items in request.data['poultry_list']:
                # if poultry exists show response
                if Poultry.objects.filter(breeding_unique_id=poultry_items['breeding_unique_id']).exists():
                    return Response({"result": "مرغداری قبلا ثبت شده است !"}, status=status.HTTP_403_FORBIDDEN)

                if poultry_items['address'] != "" or poultry_items['address'] is not None:
                    # Create Address Object
                    city = City.objects.get(key=poultry_items['address']['city_key'])  # contain city object
                    poultry_items['address'].pop('city_key')

                    # contains province object
                    province = Province.objects.get(key=poultry_items['address']['province_key'])
                    poultry_items['address'].pop('province_key')

                    # object created
                    address = SystemAddress.objects.create(**poultry_items['address'])
                    address.city = city
                    address.province = province
                    address.save()
                    poultry_items.pop('address')  # remove address key from data
                else:
                    address = None

                if poultry_items['user_bank_info'] != "" or poultry_items['user_bank_info'] is not None:
                    # Create Bank Card Object
                    bank_info = BankCard.objects.create(**poultry_items['user_bank_info'])
                    poultry_items.pop('user_bank_info')
                else:
                    bank_info = None

                wallet = Wallet()
                wallet.save()

                # tenant user key
                if 'tenant_key' in poultry_items.keys():
                    tenant_key = poultry_items['tenant_key']
                    poultry_items.pop('tenant_key')
                else:
                    tenant_key = ""

                # send data to serializer to create poultry
                serializer = PoultrySerializer(data=poultry_items)
                if serializer.is_valid():
                    poultry_object = serializer.create(validated_data=poultry_items)
                    poultry_object.user = user
                    poultry_object.incubation_date = datetime.datetime.now()
                    poultry_object.address = address
                    poultry_object.user_bank_info = bank_info
                    poultry_object.wallet = wallet
                    poultry_object.save()
                    create_province_allow_poultry_choose_kill_house = ProvinceAllowPoultryChooseKillHouse(
                        poultry=poultry_object)
                    create_province_allow_poultry_choose_kill_house.save()
                    owner_poultry = Poultry.objects.get(key=poultry_object.key)  # contains poultry owner object
                else:
                    return Response({"result": "وارد کردن تمامی مقادیر الزامیست! "}, status=status.HTTP_403_FORBIDDEN)

                if tenant_key != "":
                    # get tenant user object
                    tenant_user = self.queryset.get(key=tenant_key)

                    owner_poultry.has_tenant = True
                    owner_poultry.save()

                    # Copy Poultry Object and Create New One
                    poultry_object.pk = None
                    poultry_object.key = uuid.uuid4()
                    poultry_object.user = tenant_user
                    poultry_object.save()  # save copied object
                    poultry_object.owner = owner_poultry
                    poultry_object.wallet = wallet
                    poultry_object.save()

            user.role.add(Group.objects.get(name='Poultry'))
            return Response(status=status.HTTP_201_CREATED)
        if edit_type == "CityOperator":
            # if person != None:
            #     city_unit = CityUnit.objects.get(name=person.city.name)
            #     if CityOperator.objects.filter(address__city__name=city_unit.city.name).exists():
            #         return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE)

            serializer = create_except_profile(
                request=request,
                queryset=CityOperator,
                serializer=CityOperatorSerializer,
                role=edit_type
            )
            return Response(serializer[0], status=serializer[1])
        if edit_type == "ProvinceOperator":
            if person != None:
                province_operator = SystemUserProfile.objects.filter(role__name='ProvinceOperator',
                                                                     province=person.province)
                if province_operator.count() > 0:
                    if ProvinceOperator.objects.filter(user=province_operator.last()).exists():
                        return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE)
            if SystemUserProfile.objects.filter(role__name='ProvinceFinancial', province=person.province,
                                                key=person.key).exists():
                group = Group.objects.get(name=edit_type)
                person.role.add(group)
                return Response(status=status.HTTP_201_CREATED)
            else:

                serializer = create_except_profile(
                    request=request,
                    queryset=ProvinceOperator,
                    serializer=ProvinceOperatorSerializer,
                    role=edit_type
                )
            return Response(serializer[0], status=serializer[1])
        if edit_type == "ProvinceFinancial":
            if person != None:
                province_operator = SystemUserProfile.objects.filter(role__name='ProvinceFinancial',
                                                                     province=person.province)
                if province_operator.count() > 0:
                    if ProvinceOperator.objects.filter(user=province_operator.last()).exists():
                        return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE)
            if SystemUserProfile.objects.filter(role__name='ProvinceOperator', province=person.province,
                                                key=person.key).exists():
                group = Group.objects.get(name=edit_type)
                person.role.add(group)
                return Response(status=status.HTTP_201_CREATED)

            else:
                serializer = create_except_profile(
                    request=request,
                    queryset=ProvinceOperator,
                    serializer=ProvinceOperatorSerializer,
                    role=edit_type
                )
                return Response(serializer[0], status=serializer[1])
        if edit_type == "KillHouse":

            # contains kill house data
            kill_house_data = request.data['killhouse_data']
            request.data.pop('killhouse_data')
            if 'address' in request.data.keys():
                if request.data['address'] == "":
                    request.data.pop('address')
            if 'postal_code' in request.data.keys():
                if request.data['postal_code'] == "":
                    request.data.pop('postal_code')

            serializer = create_except_profile(
                request=request,
                queryset=KillHouseOperator,
                serializer=KillHouseOperatorSerializer,
                role=edit_type
            )

            for items in kill_house_data:
                if items['address'] != "" or items['address'] is not None:
                    # Create Address Object
                    city = City.objects.get(key=items['address']['city_key'])  # contain city object
                    items['address'].pop('city_key')

                    # contains province object
                    province = Province.objects.get(key=items['address']['province_key'])
                    items['address'].pop('province_key')
                    if items['address']['postal_code'] == "":
                        items['address'].pop('postal_code')

                    # object created
                    address = SystemAddress.objects.create(**items['address'])
                    address.city = city
                    address.province = province
                    address.save()
                    items.pop('address')  # remove address key from data
                else:
                    address = None
                if 'user_bank_info' in items.keys():
                    items.pop('user_bank_info')

                # send data to serializer to create poultry
                if 'capacity' in items.keys():
                    if items['capacity'] == "":
                        items.pop('capacity')
                if 'name' in items.keys():
                    if items['name'] == "":
                        items.pop('name')
                if 'phone' in items.keys():
                    if items['phone'] == "":
                        items.pop('phone')

                kill_house_serializer = KillHouseSerializer(data=items)
                if kill_house_serializer.is_valid():
                    kill_house_object = kill_house_serializer.create(validated_data=items)
                    kill_house_object.system_address = address
                    kill_house_object.kill_house_operator = serializer[2]
                    kill_house_object.save()
                    create_choose_steward_guilds = ProvinceAllowKillHouseChooseStewardGuilds(
                        kill_house=kill_house_object)
                    create_choose_steward_guilds.save()
                    percentage = KillHousePercentage(kill_house=kill_house_object)
                    percentage.save()
                    province_allow_kill_house_choose_steward_guilds = ProvinceAllowKillHouseChooseStewardGuilds(
                        kill_house=kill_house_object)
                    province_allow_kill_house_choose_steward_guilds.save()
                    province_allow_direct_buying = ProvinceAllowKillHouseDirectBuying(kill_house=kill_house_object)
                    province_allow_direct_buying.save()

            return Response(status=status.HTTP_201_CREATED)
        if edit_type == "KillHouseVet":
            # get kill house object
            kill_house_object = KillHouse.objects.get(key=request.data['kill_house_key'])
            request.data.pop('kill_house_key')
            if 'address' in request.data.keys():
                if request.data['address'] == "":
                    request.data.pop('address')
            if 'postal_code' in request.data.keys():
                if request.data['postal_code'] == "":
                    request.data.pop('postal_code')
            # Create Kill House Vet Object

            kill_house_vet = KillHouseVet()
            vet = Vet.objects.filter(user=person)
            if vet.count() > 0:
                vet = vet.last()
                kill_house_vet.vet = vet


            else:
                serializer = create_except_profile(
                    request=request,
                    queryset=Vet,
                    serializer=VetSerializer,
                    role=edit_type
                )
                kill_house_vet.vet = serializer[2]

            kill_house_vet.kill_house = kill_house_object
            kill_house_vet.save()

            # send object to serializer
            serializer = KillHouseVetSerializer(kill_house_vet)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        if edit_type == "Driver":
            # get user profile object
            userprofile = self.queryset.get(key=request.data['userprofile_key'])
            request.data.pop('userprofile_key')

            # Create driver Bank Account Information
            bank_info_object = BankCard.objects.create(**request.data['user_bank_info'])
            request.data.pop('user_bank_info')

            # send data to serializer for create object
            serializer = KillHouseDriverSerializer(data=request.data)
            if serializer.is_valid():
                driver_object = serializer.create(validated_data=request.data)
                driver_wallet = Wallet()
                driver_wallet.save()
                driver_object.user = userprofile
                driver_object.user_bank_info = bank_info_object
                driver_object.wallet = driver_wallet
                driver_object.save()
                userprofile.role.add(
                    Group.objects.get(name='Driver')
                )
                serializer = KillHouseDriverSerializer(driver_object)
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        if edit_type == "VetFarm":
            if Vet.objects.filter(user=person).exists():
                group = Group.objects.get(name=edit_type)
                person.role.add(group)
                return Response(status=status.HTTP_201_CREATED)
            else:
                serializer = create_except_profile(
                    request=request,
                    queryset=Vet,
                    serializer=VetSerializer,
                    role=edit_type
                )
                return Response(serializer[0], status=serializer[1])
        if edit_type == "ProvinceInspector":
            if person != None:
                province_operator = SystemUserProfile.objects.filter(role__name='ProvinceInspector',
                                                                     province=person.province)
                if province_operator.count() > 0:
                    if InspectorOperator.objects.filter(user=province_operator.last()).exists():
                        return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE)
            serializer = create_except_profile(
                request=request,
                queryset=InspectorOperator,
                serializer=InspectorOperatorSerializer,
                role=edit_type
            )
            return Response(serializer[0], status=serializer[1])

        return Response({"msg": "error"}, status=status.HTTP_403_FORBIDDEN)

    def update(self, request, pk=None, *args, **kwargs):
        # refresh(request.user.id)
        if 'second_mobile_number' in request.data.keys():
            user_profile = SystemUserProfile.objects.get(key=request.data['userprofile_key'])
            first_mobile_number = user_profile.mobile
            second_mobile_number = request.data['second_mobile_number']
            request.data.pop('second_mobile_number')
            data = {
                "first_mobile_number": first_mobile_number,
                "second_mobile_number": second_mobile_number,
            }
            req = requests.post(
                url=ARTA_URL_CHANGE_MOBILE_NUMBER,
                data=data,
                verify=False
            )
            # return Response(req.status_code)
            if req.status_code == 200:
                second_mobile_number = second_mobile_number
                # request.data.pop('userprofile_key')
                user = User.objects.get(id=user_profile.user.id)
                user.username = second_mobile_number
                user.save()
                user_profile.mobile = second_mobile_number
                user_profile.save()
            #     return Response({"result": "شماره تماس با موفقیت ویرایش شد."}, status=status.HTTP_200_OK)
            # else:
            #     return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_200_OK)
        if 'last_name' in request.data:
            if request.data['last_name'] == "":
                request.data.pop('last_name')
        if 'national_code' in request.data:
            if request.data['national_code'] == "":
                request.data.pop('national_code')
        if 'national_id' in request.data:
            if request.data['national_id'] == "":
                request.data.pop('national_id')
        edit_type = request.data['type']
        request.data.pop('type')

        person_type = request.data['person_type']
        request.data.pop('person_type')

        # edit profile & roles by user
        if person_type == 'self':
            if edit_type == 'self_profile':

                url = 'https://userbackend.rasadyar.com/user_identity/0/'
                headers = {
                    "Authorization": str(request.headers['Authorization']),
                    "Content-Type": "application/json"
                }

                # remove null fields from request
                request = remove_null_fields(type='req', request=request)
                # get profile object
                queryset = self.queryset.get(user=request.user)

                payload = {
                    'userprofile_key': str(queryset.key),
                    'mobile': queryset.mobile,
                    'first_name': queryset.first_name,
                    'last_name': queryset.last_name,
                    'national_id': queryset.national_id,
                    'national_code': queryset.national_code
                }
                req = requests.put(
                    url=url,
                    data=json.dumps(payload),
                    headers=headers,
                    verify=False
                )

                if req.status_code == 200:
                    # upload image
                    req = upload_image(req=request, field='image')

                    # send data to serializer
                    serializer = self.serializer_class(data=req.data)
                    if serializer.is_valid():
                        obj = serializer.update(validated_data=req.data, instance=queryset)
                        serializer = self.serializer_class(obj)
                        return Response(serializer.data, status=status.HTTP_200_OK)
                    return Response(serializer.errors)
                else:
                    return Response({'msg': 'Bad Request'}, status=status.HTTP_400_BAD_REQUEST)
            if edit_type == 'Poultry':
                pass
            if edit_type == "CityOperator":
                serializer = update_except_profile(
                    model=CityOperator,
                    serializer=CityOperatorSerializer,
                    request=request
                )
                return Response(serializer, status=status.HTTP_200_OK)
            if edit_type == "ProvinceOperator":
                serializer = update_except_profile(
                    model=ProvinceOperator,
                    serializer=ProvinceOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "ProvinceFinancial":
                serializer = update_except_profile(
                    model=ProvinceOperator,
                    serializer=ProvinceOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "ProvinceInspector":
                serializer = update_except_profile(
                    model=InspectorOperator,
                    serializer=InspectorOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "KillHouse":
                serializer = update_except_profile(
                    model=KillHouseOperator,
                    serializer=KillHouseOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "KillHouseVet":
                # get kill house object
                kill_house_object = KillHouse.objects.get(key=request.data['kill_house_key'])

                # get kill house vet object
                kill_house_vet_object = KillHouseVet.objects.get(key=request.data['vet_key'])

                kill_house_vet_object.kill_house = kill_house_object
                kill_house_vet_object.save()

                # send object to serializer
                serializer = KillHouseVetSerializer(kill_house_vet_object)
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "VetFarm":
                serializer = update_except_profile(
                    model=Vet,
                    serializer=VetSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "Driver":
                # get driver object
                driver = KillHouseDriver.objects.get(key=request.data['driver_key'])
                request.data.pop('driver_key')

                # send data to serializer for update
                serializer = KillHouseDriverSerializer(data=request.data)
                if serializer.is_valid():
                    driver_update = serializer.update(instance=driver, validated_data=request.data)
                    serializer = KillHouseDriverSerializer(driver_update)
                    return Response(serializer.data, status=status.HTTP_200_OK)
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        # edit profile & roles by operator
        if person_type == 'operator':
            if edit_type == 'self_profile':
                # remove null fields from request
                request = remove_null_fields(type='req', request=request)

                # get profile object
                queryset = self.queryset.get(key=request.data['userprofile_key'])
                request.data.pop('userprofile_key')

                # upload image
                req = upload_image(req=request, field='image')

                # Change Password By Operator
                if req.data['password'] != "":
                    data = {
                        'username': queryset.mobile,
                        'password': req.data['password']
                    }
                    req_change_pass = requests.post(
                        url=ARTA_URL_CHANGE_PASSWORD,
                        data=data,
                        verify=False
                    )
                    if req_change_pass.status_code == 200:
                        queryset.password = req.data['password']
                        queryset.save()
                        req.data.pop('password')
                    else:
                        return Response({"Msg": "Password Not Change"}, status=status.HTTP_400_BAD_REQUEST)
                else:
                    req.data.pop('password')

                # send data to serializer
                serializer = self.serializer_class(data=req.data)

                if serializer.is_valid():
                    # if 'city' in request.data.keys():
                    #     city = City.objects.get(key=request.data['city'])
                    #     request.data.pop('city')
                    #     queryset.city = city
                    #     queryset.save()
                    obj = serializer.update(validated_data=req.data, instance=queryset)
                    serializer = self.serializer_class(queryset)
                    return Response(serializer.data, status=status.HTTP_200_OK)
                return Response(serializer.errors)
            if edit_type == "CityOperator":
                serializer = operator_update_except_profile(
                    model=CityOperator,
                    serializer=CityOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "ProvinceOperator":
                serializer = operator_update_except_profile(
                    model=ProvinceOperator,
                    serializer=ProvinceOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "ProvinceFinancial":
                serializer = operator_update_except_profile(
                    model=ProvinceOperator,
                    serializer=ProvinceOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "ProvinceInspector":
                serializer = operator_update_except_profile(
                    model=InspectorOperator,
                    serializer=InspectorOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "Poultry":
                serializer = operator_update_except_profile(
                    model=Poultry,
                    serializer=PoultrySerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "KillHouse":
                serializer = operator_update_except_profile(
                    model=KillHouseOperator,
                    serializer=KillHouseOperatorSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "KillHouseVet":
                # get kill house object
                kill_house_object = KillHouse.objects.get(key=request.data['kill_house_key'])

                # get kill house vet object
                kill_house_vet_object = KillHouseVet.objects.get(key=request.data['vet_key'])

                kill_house_vet_object.kill_house = kill_house_object
                kill_house_vet_object.save()

                # send object to serializer
                serializer = KillHouseVetSerializer(kill_house_vet_object)
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "VetFarm":
                serializer = operator_update_except_profile(
                    model=Vet,
                    serializer=VetSerializer,
                    request=request
                )
                return Response(serializer.data, status=status.HTTP_200_OK)
            if edit_type == "Driver":
                # get driver object
                driver = KillHouseDriver.objects.get(key=request.data['driver_key'])
                request.data.pop('driver_key')

                # send data to serializer for update
                serializer = KillHouseDriverSerializer(data=request.data)
                if serializer.is_valid():
                    if driver.user_bank_info is not None:
                        bank_serializer = BankCardSerializer(data=request.data['user_bank_info'])
                        if bank_serializer.is_valid():
                            bank_object = bank_serializer.update(
                                instance=driver.user_bank_info,
                                validated_data=request.data['user_bank_info']
                            )
                            driver.user_bank_info = bank_object
                    else:
                        bank_serializer = BankCardSerializer(data=request.data['user_bank_info'])
                        if bank_serializer.is_valid():
                            bank_object = bank_serializer.create(
                                validated_data=request.data['user_bank_info']
                            )
                            driver.user_bank_info = bank_object
                            driver.save()
                    request.data.pop('user_bank_info')
                    driver_update = serializer.update(instance=driver, validated_data=request.data)
                    serializer = KillHouseDriverSerializer(driver_update)
                    return Response(serializer.data, status=status.HTTP_200_OK)
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

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

        # contains role class model
        role_class = self.object_classes[request.GET['role']]

        # get role class object
        role_object = role_class.objects.get(key=request.GET['role_data_key'])

        # deactivate role class models
        if request.GET['type'] == 'Deactivate':
            if request.GET['role'] == 'KillHouseVet':
                role_object.vet.trash = True  # set trash field to False
                role_object.vet.save()
            if request.GET['role'] == 'VetFarm':
                role_object.vet.trash = True  # set trash field to False
                role_object.vet.save()
            role_object.trash = True  # set trash field to False
            role_object.save()
            return Response({'Msg': 'Deactivated'}, status=status.HTTP_200_OK)

        # activate role class models
        elif request.GET['type'] == 'Activate':
            if request.GET['role'] == 'KillHouseVet':
                role_object.vet.trash = False  # set trash field to False
                role_object.vet.save()
            if request.GET['role'] == 'VetFarm':
                role_object.vet.trash = False  # set trash field to False
                role_object.vet.save()
            role_object.trash = False  # set trash field to False
            role_object.save()
            return Response({'Msg': 'Activated'}, status=status.HTTP_200_OK)


class SystemUserProfileّForFactorProfileViewSet(viewsets.ModelViewSet):
    queryset = SystemUserProfile.objects.all()
    serializer_class = SystemUserProfileSerializer
    permission_classes = [AllowAny]

    def update(self, request, pk=None, *args, **kwargs):
        user = SystemUserProfile.objects.get(key=request.data['userprofile_key'], trash=False)
        request.data.pop('userprofile_key')
        serializer = self.serializer_class(user)
        serializer.update(instance=user, validated_data=request.data)
        return Response(serializer.data, status=status.HTTP_200_OK)


class AdminSystemUserProfileViewSet(viewsets.ModelViewSet):
    queryset = SystemUserProfile.objects.all()
    serializer_class = SystemUserProfileSerializer
    permission_classes = [AllowAny]

    def create(self, request, *args, **kwargs):
        refresh(request.user.id)
        city = City.objects.get(key=request.data['city'])
        province = Province.objects.get(key=request.data['province'])
        address = request.data['address']
        password = request.data['password']
        role = Group.objects.get(name=request.data['role']).name
        main_address = SystemAddress(city=city, province=province, address=address)
        main_address.save()
        data = {
            "username": request.data['mobile'],
            "password": password,
            "role": role,
            "api_key": PROJECT_API_KEY
        }
        req = requests.post(
            url=ARTA_URL_REGISTER,
            data=data,
            verify=False
        )
        if req.status_code == 200:
            user = User(
                username=request.data['mobile'],
                first_name=request.data['firstname'],
                last_name=request.data['lastname']
            )
            user.save()
            base_id = SystemUserProfile.objects.all().last()
            system_profile = SystemUserProfile(
                mobile=request.data['mobile'],
                fullname=request.data['firstname'] + " " + request.data['lastname'],
                user=user,
                birthday=request.data['birthday'],
                national_id=request.data['national_id'],
                city=city,
                province=province,
                base_order=int(base_id.base_order) + 1,
                password=password
            )
            system_profile.save()
            system_profile.role.add(role)
            system_profile.save()
        if role == 'CityOperator':
            city_operator = CityOperator(user=system_profile, address=main_address)
            city_operator.save()
        elif role == 'ProvinceOperator' or role == 'ProvinceFinancial':
            province_operator = ProvinceOperator(user=system_profile, address=main_address)
            province_operator.save()
        elif role == 'ProvinceInspector':
            province_inspector = InspectorOperator(user=system_profile, address=main_address)
            province_inspector.save()
        elif role == 'KillHouse':
            kill_house_operator = KillHouseOperator(user=system_profile, address=main_address)
            kill_house_operator.save()
            kill_house = KillHouse(
                kill_house_operator=kill_house_operator,
                system_address=main_address,
                name=request.data['name'],
                capacity=request.data['capacity'],
                phone=request.data['phone'],
            )
            kill_house.save()
        elif role == 'KillHouseVet':
            vet = Vet(user=system_profile, address=main_address)
            vet.save()
            kill_house = KillHouse.objects.get(key=request.data['kill_house_key'])
            kill_house_vet = KillHouseVet(vet=vet, kill_house=kill_house)
            kill_house_vet.save()
        # elif role == 'KillHouseVet':


class CheckChickenQuntityViewSet(viewsets.ModelViewSet):
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        refresh(request.user.id)
        info_list = []
        users = UserProfile.objects.all()
        now = datetime.datetime.now() + timedelta(days=6)
        for i in range(10, 13):
            count = 0
            poultry = []
            for user in users:
                age = (now - user.hatching_date).days
                if i == age:
                    poultry.append({
                        'full_name': user.fullname,
                        'quantity': user.number_of_incubators
                    })
                    count += user.number_of_incubators

            internal_dict_info = {'age': i,
                                  'count': count,
                                  'weight': count * 3}
            internal_dict_info.update({'users': poultry})
            info_list.append(internal_dict_info)

        return Response(info_list)


# ویوست مربوط اطلاعات حساب بانکی کاربر
class BankCardViewSet(viewsets.ModelViewSet):
    queryset = BankCard.objects.all()
    serializer_class = BankCardSerializer
    permission_classes = [TokenHasReadWriteScope]

    # تابع مربوط به ثبت اطلاعات حساب بانکی کاربر
    def create(self, request, *args, **kwargs):
        # refresh(request.user.id)
        user = SystemUserProfile.objects.get(user=request.user)
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            bank_card = serializer.create(validated_data=request.data)
            if 'role' in request.GET:
                if request.GET['role'] == 'Poultry':
                    poultry = Poultry.objects.get(key=request.data['key'])
                    poultry.user_bank_info = bank_card
                    poultry.save()
                elif request.GET['role'] == 'CityOperator':
                    city_operator = CityOperator.objects.get(user=user)
                    city_operator.user_bank_info = bank_card
                    city_operator.save()
                elif request.GET['role'] == 'ProvinceFinancial':
                    province_operator = ProvinceOperator.objects.get(user=user)
                    province_operator.user_bank_info = bank_card
                    province_operator.save()
                elif request.GET['role'] == 'KillHouse':
                    kill_house_operator = KillHouseOperator.objects.get(user=user)
                    kill_house_operator.user_bank_info = bank_card
                    kill_house_operator.save()
                elif request.GET['role'] == 'Vet':
                    vet = Vet.objects.get(user=user)
                    vet.user_bank_info = bank_card
                    vet.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors)

    # تابع مربوط به ویرایش اطلاعات حساب بانکی کاربر
    def update(self, request, pk=None, *args, **kwargs):
        # refresh(request.user.id)
        bank_card = BankCard.objects.get(key__exact=request.data["key"])
        request.data.pop('key')
        bank_card.save()
        serializer = self.serializer_class(bank_card)
        serializer.update(instance=bank_card, validated_data=request.data)
        return Response(serializer.data, status=status.HTTP_200_OK)


class ProvinceChangeBankCardViewSet(viewsets.ModelViewSet):
    queryset = BankCard.objects.all()
    serializer_class = BankCardSerializer
    permission_classes = [TokenHasReadWriteScope]

    # تابع مربوط به ثبت اطلاعات حساب بانکی کاربر
    def create(self, request, *args, **kwargs):
        # refresh(request.user.id)
        role = request.data['role']
        if role == 'Poultry':
            poultry = Poultry.objects.get(key=request.data['poultry_key'], trash=False)
            if poultry.user_bank_info != None:
                request.data.pop('role')
                request.data.pop('poultry_key')
                bank_card = BankCard.objects.get(key=poultry.user_bank_info.key)
                serializer = self.serializer_class(bank_card)
                serializer.update(instance=bank_card, validated_data=request.data)
            else:
                request.data.pop('role')
                request.data.pop('poultry_key')
                serializer = self.serializer_class(data=request.data)
                if serializer.is_valid():
                    bank_card = serializer.create(validated_data=request.data)
                    poultry.user_bank_info = bank_card
                    poultry.save()
        else:
            operator = ProvinceOperator.objects.filter(key=request.data['operator_key'], trash=False)
            if operator.user_bank_info != None:
                request.data.pop('role')
                request.data.pop('operator_key')
                bank_card = BankCard.objects.get(key=operator.user_bank_info.key)
                serializer = self.serializer_class(bank_card)
                serializer.update(instance=bank_card, validated_data=request.data)
            else:
                request.data.pop('role')
                request.data.pop('poultry_key')
                serializer = self.serializer_class(data=request.data)
                if serializer.is_valid():
                    bank_card = serializer.create(validated_data=request.data)
                    operator.user_bank_info = bank_card
                    operator.save()
        return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK)


# ویوست مربوط آدرس کاربر
class AddressViewSet(viewsets.ModelViewSet):
    queryset = Address.objects.all()
    serializer_class = AddressSerializer
    permission_classes = [TokenHasReadWriteScope]

    def list(self, request, *args, **kwargs):
        if "key" in request.GET:
            add_obj = Address.objects.get(key__exact=request.GET["key"])
            serializer = self.serializer_class(add_obj)
            return Response(serializer.data, status=status.HTTP_200_OK)
        if "title" in request.GET:
            add_obj = Address.objects.filter(user_id=request.user.id)
            query = [x for x in add_obj]
            serializer = self.serializer_class(query, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            queryset = Address.objects.all()
            serializer = self.serializer_class(queryset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

    def create(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            address = serializer.create(validated_data=request.data)
            address.user = UserProfile.objects.get(user=request.user)
            address.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors)

    def retrieve(self, request, pk=None, *args, **kwargs):
        queryset = Address.objects.get(key__exact=request.GET["key"])
        serializer = self.serializer_class(queryset)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def update(self, request, pk=None, *args, **kwargs):
        queryset = Address.objects.get(key__exact=request.GET["key"])
        queryset.save()
        serializer = self.serializer_class(queryset)
        serializer.update(instance=queryset, validated_data=request.data)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def partial_update(self, request, pk=None, *args, **kwargs):
        pass

    def destroy(self, request, pk=None, *args, **kwargs):
        queryset = Address.objects.get(key__exact=request.GET["wallet_id"])
        queryset.trash = True
        queryset.save()
        return Response(status=status.HTTP_200_OK)


@api_view(['POST'])
@permission_classes([AllowAny])
def new_send_otp(request):
    # if request.headers['Origin'] == 'test.sstit.ir':
    #     return redirect('test.ravandno.ir')
    # else:
    req = requests.post(
        url=ARTA_URL_SEND_OTP,
        data=request.data,
        verify=False
    )

    return Response(req.json())


# تابع برای برای بررسی یکسان بودن کد پیامکی استفاده میشود
@api_view(["POST"])
@permission_classes([AllowAny])
def check_otp(request):
    req = requests.post(
        url=ARTA_URL_CHECK_OTP,
        data=request.data,
        verify=False
    )
    return Response(req.json(), status=status.HTTP_200_OK)


@api_view(["POST"])
@permission_classes([TokenHasReadWriteScope])
@authentication_classes([OAuth2Authentication])
def change_password(request):
    user = SystemUserProfile.objects.get(user=request.user)
    req = requests.post(
        url=ARTA_URL_CHANGE_PASSWORD,
        data=request.data,
        verify=False
    )
    if req.status_code == 200:
        user.password = request.data['password']
        user.save()

    return Response(req.json(), status=status.HTTP_200_OK)


@api_view(['POST'])
@permission_classes([AllowAny])
def new_register(request):
    req = requests.post(
        url=ARTA_URL_REGISTER,
        data=request.data,
        verify=False
    )
    if req.status_code == 500:
        error_message = req.content.decode('utf-8')  # Decode response content
        return Response(error_message)
    if req.status_code == 200:
        role = Group.objects.get(name=request.data['role'])
        password = request.data['password']
        user = User(
            username=request.data['username'],
            password=cryptocode.encrypt(password, password)
        )
        user.save()
        userprofile = SystemUserProfile(
            user=user,
            mobile=request.data['username'],
            password=password
        )

        userprofile.base_order = \
            1000 if len(SystemUserProfile.objects.all()) == 0 \
                else SystemUserProfile.objects.all().order_by('create_date').last().base_order + 1
        userprofile.save()
        userprofile.role.add(role)

        # add tenant for a Poultry
        if 'tenant' in request.data.keys():

            # Check if has access
            if get_authorization_header(request) != "":
                # complete UserProfile information
                province = Province.objects.get(key=request.data['tenant']['province'])
                city = City.objects.get(key=request.data['tenant']['city'])
                userprofile.province = province
                userprofile.city = city
                userprofile.national_code = request.data['tenant']['national_code']
                userprofile.first_name = request.data['tenant']['first_name']
                userprofile.last_name = request.data['tenant']['last_name']
                userprofile.save()

                # set the tenant poultry owner
                owner_poultry = Poultry.objects.get(key=request.data['tenant']['poultry_key'])
                owner_poultry.has_tenant = True
                owner_poultry.save()

                # create tenant
                address = SystemAddress(
                    city=city,
                    province=province,
                    address=request.data['tenant']['address'],
                    postal_code=request.data['tenant']['postal_code']
                )
                address.save()
                tenant_poultry = Poultry(
                    user=userprofile,
                    owner=owner_poultry,
                    unit_name=owner_poultry.unit_name,
                    breeding_unique_id=request.data['tenant']['unique_id'],
                    address=address
                )
                tenant_poultry.tenant = True
                tenant_poultry.save()
                serializer = PoultrySerializer(tenant_poultry)
                return Response(serializer.data, status=status.HTTP_201_CREATED)

        access_token = AccessToken(
            token=req.json()['access_token'],
            user=user,
            expires=req.json()['expire_time'],
            scope="read write"
        )
        access_token.save()
        return Response(req.json(), status.HTTP_201_CREATED)
    if req.status_code == 400:
        return Response({"result": 'کاربر قبلا ثبت شده است !'}, status.HTTP_403_FORBIDDEN)


# @api_view(['POST'])
# @permission_classes([AllowAny])
# def new_login(request):
#     if User.objects.filter(username__exact=request.data['username']).exists():
#         user = User.objects.get(username__exact=request.data['username'])
#         userprofile = SystemUserProfile.objects.get(
#             user=user
#         )
#
#         # for recognize if user role are deactivated can not login
#         role_classes = SystemUserProfileViewSet.object_classes
#         role_object = role_classes[request.data['role']].objects.filter(user=userprofile)
#         for item in role_object:
#             if item.trash == False:
#                 return Response(status=status.HTTP_203_NON_AUTHORITATIVE_INFORMATION)
#         # ##########################################################################
#
#         roles = []
#         for item in userprofile.role.all():
#             roles.append(item.name)
#         request.data['role'] = roles
#         request.data['user_key'] = str(userprofile.key)
#         req = requests.post(
#             url=ARTA_URL_LOGIN,
#             json=request.data,
#             verify=False
#         )
#         if req.status_code == 200:
#             access_token = AccessToken(
#                 user=user,
#                 token=req.json()['access_token'],
#                 expires=req.json()['expire_time'],
#                 scope="read write"
#             )
#             access_token.save()
#             userprofile.token = access_token.token
#             userprofile.save()
#             for item in req.json()['role']:
#                 group = Group.objects.get(name=item)
#                 if not SystemUserProfile.objects.filter(user=user, role=group):
#                     userprofile.role.add(group)
#             internal_login_dict = {
#                 "access_token": req.json()['access_token'],
#                 "expires_in": req.json()['token_type'],
#                 "scope": req.json()['scope'],
#                 "expire_time": req.json()['expire_time'],
#                 "mobile": userprofile.mobile,
#                 "fullname": userprofile.fullname,
#                 "firstname": userprofile.first_name,
#                 "lastname": userprofile.last_name,
#                 "city": userprofile.city.name,
#                 "province": userprofile.province.name,
#                 "national_code": userprofile.national_code,
#                 "national_id": userprofile.national_id,
#                 "birthday": userprofile.birthday,
#                 "image": userprofile.image,
#                 "base_order": userprofile.base_order,
#                 "role": req.json()['role'],
#             }
#
#             return Response(internal_login_dict, status.HTTP_200_OK)
#         if req.status_code == 401:
#             return Response({'msg': 'unauthorized'}, status.HTTP_401_UNAUTHORIZED)
#     else:
#         return Response({'msg': 'unauthorized'}, status.HTTP_401_UNAUTHORIZED)


def expire_user_access_tokens(token,user):
    now = datetime.datetime.now().date()
    accesses = AccessToken.objects.filter(user=user,created__date=now).exclude(token=token).order_by('-created')
    accesses_to_expire = accesses[1:]
    for access in accesses_to_expire:
        access.expires = now - timedelta(days=2)
        access.save()


def create_login_log(request, user_profile):
    headers = dict(request.headers)

    UserLoginLog.objects.create(
        user_profile=user_profile,
        headers=headers,
        ip_address=request.META.get('REMOTE_ADDR'),
        user_agent=request.META.get('HTTP_USER_AGENT')
    )


@api_view(['POST'])
@permission_classes([AllowAny])
def new_login(request):
    username = request.data['username']
    if User.objects.filter(username__exact=username).exists():
        user = User.objects.get(username__exact=username)
        userprofile = SystemUserProfile.objects.get(user=user)
        roles = list(userprofile.role.all().values_list('name', flat=True))
        request.data['role'] = roles
        request.data['user_key'] = str(userprofile.key)
        req_data = {
            "api_key": PROJECT_API_KEY,
            "password": request.data['password'],
            "username": request.data['username'],
            "user_key": str(userprofile.key),
            "role": roles,
        }
        req = requests.post(
            url=ARTA_URL_LOGIN,
            json=req_data,
            verify=False
        )
        if req.status_code == 200:
            expires_datetime = datetime.datetime.strptime(req.json()['expire_time'],
                                                          "%Y-%m-%dT%H:%M:%S.%f") + datetime.timedelta(days=1)
            access_token = AccessToken(
                user=user,
                token=req.json()['access_token'],
                expires=expires_datetime,
                scope="read write"
            )
            access_token.save()
            userprofile.token = access_token.token
            userprofile.save()
            for item in req.json()['role']:
                group = Group.objects.get(name=item)
                if not SystemUserProfile.objects.filter(user=user, role=group):
                    userprofile.role.add(group)
            internal_login_dict = {
                "access_token": req.json()['access_token'],
                "expires_in": req.json()['token_type'],
                "scope": req.json()['scope'],
                "expire_time": req.json()['expire_time'],
                "mobile": userprofile.mobile,
                "fullname": userprofile.fullname,
                "firstname": userprofile.first_name,
                "lastname": userprofile.last_name,
                "city": userprofile.city.name,
                "province": userprofile.province.name,
                "national_code": userprofile.national_code,
                "national_id": userprofile.national_id,
                "birthday": userprofile.birthday,
                "image": userprofile.image,
                "base_order": userprofile.base_order,
                "role": req.json()['role'],
            }
            # expire_user_access_tokens_tread = threading.Thread(target=expire_user_access_tokens, args=(req.json()['access_token'],user))
            # expire_user_access_tokens_tread.start()
            try:
                create_login_log(request, userprofile)
            except:
                pass
            return Response(internal_login_dict, status.HTTP_200_OK)
        if req.status_code == 401:
            return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE)
    else:
        return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE)
# def new_login(request):
#     username = request.data['username']
#     password = (request.data['password'],)
#
#     if User.objects.filter(username__exact=username).exists():
#         user = User.objects.get(username__exact=username)
#         userprofile = SystemUserProfile.objects.get(user=user)
#         decrypted_password = cryptocode.decrypt(user.password, password[0])
#         if decrypted_password != password[0]:
#             return Response({'result': 'رمز ورود اشتباه است!'}, status=status.HTTP_401_UNAUTHORIZED)
#         roles = list(userprofile.role.all().values_list('name', flat=True))
#         data = {
#             "username": user.username,
#             "password": userprofile.password,
#             "client_id": CLIENT_ID,
#             "client_secret": CLIENT_SECRET,
#             "grant_type": "client_credentials",
#             "scope": "read write",
#         }
#
#         r = requests.post(url=BASE_URL + "token/", data=json.dumps(data), verify=False)
#         access_token = AccessToken.objects.get(token=r.json()["access_token"])
#         access_token.user = user
#         access_token.expires += timedelta(days=3)
#         access_token.save()
#         userprofile.token = access_token.token
#         userprofile.save()
#         internal_login_dict = {
#             "access_token": access_token.token,
#             "expires_in": access_token.expires,
#             "scope": "read write",
#             "expire_time": access_token.expires,
#             "mobile": userprofile.mobile,
#             "fullname": userprofile.fullname,
#             "firstname": userprofile.first_name,
#             "lastname": userprofile.last_name,
#             "city": userprofile.city.name,
#             "province": userprofile.province.name,
#             "national_code": userprofile.national_code,
#             "national_id": userprofile.national_id,
#             "birthday": userprofile.birthday,
#             "image": userprofile.image,
#             "base_order": userprofile.base_order,
#             "role": roles,
#         }
#
#         return Response(internal_login_dict, status.HTTP_200_OK)
#
#     else:
#         return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE)


# تابع مربوط به ازسال کد پیامکی برای چند حالت استفاده می شود
# یرای فراموشی رمز عبور و برای تغییر رمز عبور و تغییر موبایل و ...
# @api_view(["POST"])
# @permission_classes([AllowAny])
# def send_otp(request):
#     mobile = request.data["mobile"]
#     state = request.data["state"]
#     if len(mobile) < 11 or len(mobile) > 11:
#         return Response({"pattern": "wrong", }, status=status.HTTP_403_FORBIDDEN, )
#     key = str(uuid.uuid4())
#     rand = random.randint(10000, 99000)
#     cache.set(key, str(rand), timeout=CACHE_TTL)
#     userprofile = SystemUserProfile.objects.filter(mobile=mobile)
#
#     if userprofile.count() == 0:
#         return Response({"is_user": False}, status=status.HTTP_404_NOT_FOUND)
#
#     elif state == "forget_password":
#         receptor = mobile
#         send_otp_code(receptor, rand)
#         return Response({"is_user": True, "key": key}, status=status.HTTP_200_OK)
#
#     elif state == "change_password":
#         receptor = mobile
#         send_otp_code(receptor, rand)
#         return Response({"is_user": True, "key": key}, status=status.HTTP_200_OK, )
#
#     elif state == "change_mobile":
#         receptor = mobile
#         send_otp_code(receptor, rand)
#         return Response({"state": "change_mobile", "key": key}, status=status.HTTP_200_OK)
#
#     elif state == "":
#         list1 = []
#         if userprofile.count() > 1:
#
#             for user in userprofile:
#                 user_dict = {
#                     "userprofile_id": user.id,
#                     "fullname": user.fullname,
#                     "first_name": user.first_name,
#                     "last_name": user.last_name,
#                     "mobile": user.mobile,
#                     "role": user.role.name,
#                     "province": user.address.province,
#                     "city": user.address.city,
#                     "address": user.address.address
#                 }
#                 list1.append(user_dict)
#             return Response(
#                 {
#                     "result": list1,
#                 },
#                 status=status.HTTP_200_OK,
#             )
#
#         else:
#
#             return Response(
#                 {
#                     "is_user": True,
#                 },
#                 status=status.HTTP_200_OK,
#             )


@api_view(["POST"])
@permission_classes([AllowAny])
def login(request):
    username = request.data["mobile"]
    password = request.data["password"]
    api_key = request.data["api_key"]
    data = {
        "username": username,
        "password": password,
        "api_key": api_key,
    }
    r = requests.post(url=ARTA_URL_LOGIN, data=data)
    if "is_user" in r.json().keys():
        return Response({'is_user': False}, status=status.HTTP_401_UNAUTHORIZED)
    elif "password" in r.json().keys():
        return Response({'password': 'wrong'}, status=status.HTTP_401_UNAUTHORIZED)
    user_profile = UserProfile.objects.get(mobile=username)
    user = User.objects.get(id=user_profile.user.id)
    user_profile.token = r.json()["access_token"]
    user_profile.save()
    access = AccessToken(token=r.json()['access_token'], user=user, scope=r.json()['scope'],
                         expires=r.json()['expire_time'])
    access.save()
    role = Group.objects.get(id=user_profile.role.id)
    response = {
        "access_token": r.json()['access_token'],
        "expires_in": r.json()['expires_in'],
        "token_type": r.json()['token_type'],
        "scope": r.json()['scope'],
        "role": role.name
    }
    return Response(response, status=status.HTTP_200_OK)


@api_view(["POST"])
@permission_classes([AllowAny])
def register(request):
    username = request.data["username"]
    password = request.data["password"]
    api_key = request.data["api_key"]
    province = request.data['province']
    city = request.data['city']
    role = request.data['role']
    role = Group.objects.get(name=role)
    data = {
        "username": username,
        "password": password,
        "api_key": api_key,
    }
    r = requests.post(url=ARTA_URL_REGISTER, data=data)
    if 'result' in r.json().keys():
        return Response({"result": "user already exist"})

    user = User(
        username=username, password=cryptocode.encrypt(password, password)
    )
    user.save()
    access = AccessToken(token=r.json()['access_token'], user=user, scope=r.json()['scope'],
                         expires=r.json()['expire_time'])
    access.save()

    address = Address(province=province, city=city)
    address.save()
    userprofile = UserProfile(user=user, mobile=username, address=address, role=role)
    userprofile.base_order = 1000 if len(UserProfile.objects.all()) == 0 else UserProfile.objects.all().order_by(
        'create_date').last().base_order + 1
    userprofile.user = user
    userprofile.token = r.json()['access_token']
    userprofile.save()
    return Response(r.json(), status=status.HTTP_200_OK)


@api_view(["POST"])
@permission_classes([AllowAny])
# @authentication_classes([OAuth2Authentication])
def forget_password(request):
    # user = SystemUserProfile.objects.get(user=request.user)
    # user.password = request.data['password']
    # user.save()
    req = requests.post(
        url=ARTA_URL_CHANGE_PASSWORD,
        data=request.data,
        verify=False
    )
    if req.status_code == 200:
        user = SystemUserProfile.objects.get(mobile=request.data['username'])

        user.password = request.data['password']
        user.save()

    return Response(req.json(), status=status.HTTP_200_OK)

    # mobile = request.data["mobile"]
    # password = request.data["password"]
    # try:
    #     userprofile = UserProfile.objects.get(mobile__exact=mobile)
    # except UserProfile.DoesNotExist:
    #     return Response(status=status.HTTP_401_UNAUTHORIZED)
    # user = User.objects.get(id=userprofile.user.id)
    # user.password = cryptocode.encrypt(password, password)
    # user.save()
    # data = {
    #     "username": str(user.username),
    #     "password": user.password,
    #     "client_id": CLIENT_ID,
    #     "client_secret": CLIENT_SECRET,
    #     "grant_type": "client_credentials",
    #     "scope": "read write",
    # }
    # r = requests.post(url=BASE_URL + "token/", data=json.dumps(data))
    # userprofile.token = r.json()["access_token"]
    # userprofile.save()
    # access = AccessToken.objects.get(token=userprofile.token)
    # access.user = userprofile.user
    # access.save()
    # role = Group.objects.get(id=userprofile.role.id)
    # response = {
    #     "access_token": r.json()['access_token'],
    #     "expires_in": r.json()['expires_in'],
    #     "token_type": r.json()['token_type'],
    #     "scope": r.json()['scope'],
    #     "role": role.name
    # }
    # return Response(response, status=status.HTTP_200_OK)


# @api_view(["GET"])
# @permission_classes([AllowAny])
# تابع برای گرفتن گزارش  تعداد جوجه و سن جوجه مرغداران استفاده میشود که بصورت فایل اکسل است
def resulting(request):
    list2 = []
    today = datetime.datetime.now()
    if 'age' in request.GET:
        users = UserProfile.objects.filter(role_id=1).exclude(incubation_date=None)
        for user in users:
            age = (today - user.incubation_date).days
            if int(age) == int(request.GET['age']):
                list2.append(user)
    elif 'state' in request.GET:
        users = UserProfile.objects.filter(role_id=1).exclude(incubation_date=None)
        for user in users:
            age = (today - user.incubation_date).days
            if int(age) >= int(request.GET['age1']) and int(age) <= int(request.GET['age2']):
                list2.append(user)
    excel_options = [
        'نام و نام خانوادگی'
        , 'تاریخ جوجه ریزی'
        , 'سن مرغ'
        , 'تعداد جوجه ریزی',
        'شماره همراه', 'استان',
        'شهرستان',
        'آدرس'
    ]
    output = BytesIO()
    workbook = xlsxwriter.Workbook(output)
    worksheet = workbook.add_worksheet()
    for count in range(len(excel_options)):
        worksheet.write(0, count, excel_options[count])
    l = 0
    for user in list2:
        l += 1
        today = datetime.datetime.now()
        if user.incubation_date != None:
            age = (today - user.incubation_date).days
            gregorian_date = jdatetime.date.fromgregorian(
                day=user.incubation_date.day,
                month=user.incubation_date.month,
                year=user.incubation_date.year
            )
            incubation_date = gregorian_date
        else:
            age = 'ندارد'
            incubation_date = 'ندارد'
        list1 = [
            user.fullname,
            str(incubation_date),
            str(age),
            user.number_of_incubators,
            user.mobile,
            user.address.province,
            user.address.city,
            user.address.address,
        ]
        for item in range(len(list1)):
            worksheet.write(l, item, list1[item])
        list1 = []
    workbook.close()
    output.seek(0)

    response = HttpResponse(content_type='application/vnd.ms-excel')

    response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"'
    response.write(output.getvalue())

    return response


# تابع برای دریافت گزارش اطلاعات مربوط به فاکتور های مرغ منجمد به صورت فایل اکسل استفاده میشود
def ware_house_factor(request):
    list2 = []
    factors = WareHouseFactor.objects.filter(trash=False).order_by('create_date')
    for factor in factors:
        list2.append(factor)

    excel_options = [
        'تاریخ',
        'نام و نام خانوادگی',
        'کدملی'
        , 'شماره همراه'
        , 'نوع کالا'
        ,
        'شماره نامه جهاد',
        'شماره نامه استان',
        'قیمت',
        'وزن'
    ]
    output = BytesIO()
    workbook = xlsxwriter.Workbook(output)
    worksheet = workbook.add_worksheet()
    for count in range(len(excel_options)):
        worksheet.write(0, count, excel_options[count])
    l = 0
    for factor in factors:
        l += 1
        gregorian_date = jdatetime.date.fromgregorian(
            day=factor.date.day,
            month=factor.date.month,
            year=factor.date.year
        )
        list1 = [
            str(gregorian_date),
            factor.customer,
            str(factor.national_code),
            factor.mobile,
            factor.product_type,
            str(factor.letter_number_jahad),
            factor.letter_number,
            factor.fee,
            factor.weight
        ]
        for item in range(len(list1)):
            worksheet.write(l, item, list1[item])

        list1 = []

    workbook.close()
    output.seek(0)

    response = HttpResponse(content_type='application/vnd.ms-excel')

    response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"'
    response.write(output.getvalue())

    return response


@api_view(['POST'])
@permission_classes([AllowAny])
def pos_login(request):
    build_id = None
    link = None
    pos_version = PosVersion.objects.filter(trash=False).first()
    if pos_version:
        build_id = pos_version.build_id
        link = pos_version.latest_downloadlink
    try:
        pos = POSMachine.objects.get(pos_id=request.data['pos-id'], trash=False)
        if pos.active == False:
            return Response({"result": "این کلید غیر فعال میباشد! "}, status=status.HTTP_401_UNAUTHORIZED)


    except:
        return Response({"result": "دستگاه پوزی با این شناسه وجود ندارد! "}, status=status.HTTP_401_UNAUTHORIZED)

    if User.objects.filter(username__exact=pos.user.mobile).exists():
        user = User.objects.get(username__exact=pos.user.mobile)
        userprofile = SystemUserProfile.objects.get(
            user=user
        )
        data = {
            "username": user.username,
            "password": userprofile.password,
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET,
            "grant_type": "client_credentials",
            "scope": "read write",
        }

        r = requests.post(url=BASE_URL + "token/", data=json.dumps(data), verify=False)
        access_token = AccessToken.objects.get(token=r.json()["access_token"])
        access_token.user = user
        access_token.expires += timedelta(days=3)
        access_token.save()
        userprofile.token = access_token.token
        userprofile.save()
        pos.token = access_token.token
        pos.save()
        if pos.guild:
            store_name = pos.guild.guilds_name
            phone = pos.guild.phone
        else:
            store_name = pos.kill_house.name
            phone = pos.kill_house.phone
        internal_login_dict = {
            "access_token": userprofile.token,
            "build_id": build_id,
            "latest_downloadlink": link,
            "profile": {
                "pos_id": pos.pos_id,
                "store_name": store_name,
                "phone": phone,
                "mobile": userprofile.mobile,
                "fullname": userprofile.fullname,
                "firstname": userprofile.first_name,
                "lastname": userprofile.last_name,
                "city": userprofile.city.name,
                "province": userprofile.province.name,
                "national_code": userprofile.national_code,
                "national_id": userprofile.national_id,
                "birthday": userprofile.birthday,
            }

        }
        for pos_item in PosItem.objects.all():
            internal_login_dict[pos_item.name] = pos_item.value

        return Response(internal_login_dict, status.HTTP_200_OK)

    else:
        return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE)


@api_view(['POST'])
@permission_classes([AllowAny])
def new_pos_login(request):
    pos_id = request.data.get('pos-id')
    pos = get_object_or_404(POSMachine, pos_id=pos_id, trash=False)

    if not pos.active:
        return Response({"result": "این کلید غیر فعال میباشد! "}, status=status.HTTP_401_UNAUTHORIZED)

    user = get_object_or_404(User, username=pos.user.mobile)
    user_profile = get_object_or_404(SystemUserProfile, user=user)

    pos_info = get_pos_info(pos)

    data = {
        "username": user.username,
        "password": user_profile.password,
        "client_id": CLIENT_ID,
        "client_secret": CLIENT_SECRET,
        "grant_type": "client_credentials",
        "scope": "read write",
    }

    response = requests.post(url=f"{BASE_URL}token/", data=json.dumps(data), verify=False)
    access_token = update_access_token(response.json()["access_token"], user)

    user_profile.token = access_token.token
    user_profile.save()

    pos.token = access_token.token
    pos.save()

    internal_login_dict = build_internal_login_response(user_profile, pos_info, pos.pos_id)

    return Response(internal_login_dict, status.HTTP_200_OK)


def get_pos_info(pos):
    if pos.kill_house:
        return {
            "type": "KillHouse",
            "name": pos.kill_house.name,
            "phone": pos.kill_house.phone
        }
    elif pos.guild:
        return {
            "type": "Guild",
            "name": pos.guild.guilds_name,
            "phone": pos.guild.phone
        }
    else:
        return {
            "type": "Dispenser",
            "name": pos.dispenser.user.fullname,
            "phone": pos.dispenser.user.mobile
        }


def update_access_token(token_str, user):
    access_token = AccessToken.objects.get(token=token_str)
    access_token.user = user
    access_token.expires += timedelta(days=3)
    access_token.save()
    return access_token


def build_internal_login_response(user_profile, pos_info, pos_id):
    return {
        "access_token": user_profile.token,
        "type": pos_info["type"],
        "profile": {
            "pos_id": pos_id,
            "name": pos_info["name"],
            "phone": pos_info["phone"],
            "mobile": user_profile.mobile,
            "fullname": user_profile.fullname,
            "firstname": user_profile.first_name,
            "lastname": user_profile.last_name,
            "city": user_profile.city.name,
            "province": user_profile.province.name,
            "national_code": user_profile.national_code,
            "national_id": user_profile.national_id,
            "birthday": user_profile.birthday,
        }
    }


@api_view(['POST'])
@permission_classes([AllowAny])
def show_transaction_info(request):
    request.data['registered'] = True
    return Response(request.data)


@api_view(['POST'])
@permission_classes([AllowAny])
def TokenVerification(request):
    token = AccessToken.objects.get(token=request.data['token'])
    user = SystemUserProfile.objects.filter(user=token.user, trash=False).select_related('province', 'city').first()

    return Response({
        "username": user.mobile,
        "password": user.password,
        "province": user.province.name,
        "city": user.city.name,
    })

    # def create(self, request, *args, **kwargs):
    #     group = Group.objects.filter(name__in=request.data['roles'])
    #     users = SystemUserProfile.objects.filter(trash=False,role__in=group).order_by('id')
    #     notis_user = users.values_list('id',flat=True)
    #     return Response(notis_user)
    #     serializer = self.serializer_class(data=request.data)
    #     if serializer.is_valid():
    #         notice = serializer.create(validated_data=request.data)
    #         notice.users = notis_user
    #         notice.save()
    #         for user in notis_user:
    #             user_notice = UserNoticeInfo(
    #                 notice=notice,
    #                 user = user,
    #
    #             )
    #             user_notice.save()
    #         serializer = self.serializer_class(notice)
    #         return Response(serializer.data)
    #     return Response(serializer.errors)


@api_view(['POST'])
@permission_classes([AllowAny])
def register_tenant(request):
    province = Province.objects.get(key=request.data['province'])
    city = City.objects.get(key=request.data['city'])
    breeding_uniq_id = request.data['unique_id']
    if Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).exists():
        return Response({'result': 'شناسه یکتا برای شخص دیگری است!'}, status=status.HTTP_403_FORBIDDEN)
    owner_poultry = Poultry.objects.get(key=request.data['poultry_key'])
    owner_poultry.has_tenant = True

    address = SystemAddress(
        city=city,
        province=province,
        address=request.data['address'],
        postal_code=request.data['postal_code']
    )
    address.save()
    tenant_poultry = Poultry(
        user=owner_poultry.user,
        owner=owner_poultry,
        unit_name=request.data['unit_name'],
        breeding_unique_id=breeding_uniq_id,
        address=address,
        city_number=city.id,
        province_number=province.id,
        city_name=city.name,
        province_name=province.name
    )
    tenant_poultry.tenant = True
    owner_poultry.save()
    tenant_poultry.save()
    serializer = PoultrySerializer(tenant_poultry)
    return Response(serializer.data, status=status.HTTP_201_CREATED)
