from django.utils import timezone
from django.utils.decorators import decorator_from_middleware_with_args, method_decorator
from rest_framework import status
from rest_framework.views import APIView

from authenticate.middleware import AuthorizatorMiddleware
from payment.models import UserBalanceHistory
from plan.models import AbstractUserPlan, UserPlan
from plan.serializers import AbstractUserPlanListSerializer, AbstractUserPlanListInputValidator, AbstractUserPlanPurchaseInputValidator, \
    UserPlanGetSerializer
from utils.myresponse import MyResponse
from wikiazma.middleware import SerializerValidationMiddleware

serializer_validation_middleware = decorator_from_middleware_with_args(
    SerializerValidationMiddleware)
user_token_or_server_token_or_server_API_key_validation_and_authorization = decorator_from_middleware_with_args(
    AuthorizatorMiddleware)


@method_decorator(serializer_validation_middleware(AbstractUserPlanListInputValidator), name='post')
class AbstractUserPlanList(APIView):
    def post(self, request):
        skip = request.middleware_serializer_data.get('skip')
        take = request.middleware_serializer_data.get('take')

        plans = AbstractUserPlan.objects.all()[skip:skip + take]

        plans_data = AbstractUserPlanListSerializer(plans, many=True).data
        return MyResponse(request, {'status': 'ok', 'message': 'Successful', 'data': {'plans': plans_data}}, status=status.HTTP_200_OK)


@method_decorator(user_token_or_server_token_or_server_API_key_validation_and_authorization(accept_user_token=True),
                  name='post')
class UserPlanGet(APIView):
    def post(self, request):
        user = request.middleware_user

        try:
            user_plan = UserPlan.objects.get(user=user)
            user_plan_data = UserPlanGetSerializer(user_plan).data
        except:
            user_plan_data = None

        return MyResponse(request, {'status': 'ok', 'message': 'Successful', 'data': {'user_plan': user_plan_data}}, status=status.HTTP_200_OK)


@method_decorator(user_token_or_server_token_or_server_API_key_validation_and_authorization(accept_user_token=True),
                  name='post')
@method_decorator(serializer_validation_middleware(AbstractUserPlanPurchaseInputValidator), name='post')
class AbstractUserPlanPurchase(APIView):
    def post(self, request):
        abstract_user_plan_id = request.middleware_serializer_data.get(
            'abstract_user_plan_id')

        user = request.middleware_user

        abstract_user_plan = AbstractUserPlan.objects.get(
            pk=abstract_user_plan_id)
        total_cost = abstract_user_plan.get_final_price()

        user_balance = UserBalanceHistory.get_last_user_balance(
            request.middleware_user).remaining_balance
        if user_balance < total_cost:
            return MyResponse(request, {'status': 'error', 'message': 'balance is not enough',
                                        'data': {'total_cost': total_cost, 'balance': user_balance}},
                              status=status.HTTP_402_PAYMENT_REQUIRED)

        from quiz.utils import quiz_purchase_wikiazma_balance_handler, quiz_purchase_user_balance_handler
        quiz_purchase_wikiazma_balance_handler(
            quiz=None, reason_meta_data={'abstract_user_plan_id': str(abstract_user_plan_id)}, user=user, amount=total_cost)
        quiz_purchase_user_balance_handler(
            user=user, quiz=None, reason_meta_data={'abstract_user_plan_id': str(abstract_user_plan_id)}, amount=-1 * total_cost)

        try:
            user_plan = UserPlan.objects.get(user=user)
        except:
            user_plan = UserPlan()
            user_plan.user = user

        user_plan.name = abstract_user_plan.name
        user_plan.purchased_price = abstract_user_plan.get_final_price()
        user_plan.wage_factor = abstract_user_plan.wage_factor
        user_plan.tax_factor = abstract_user_plan.tax_factor
        user_plan.min_wage_fee = abstract_user_plan.min_wage_fee
        user_plan.max_institutes_per_user = abstract_user_plan.max_institutes_per_user
        user_plan.start_date = timezone.now()
        user_plan.end_date = timezone.now() + abstract_user_plan.duration

        user_plan.save()

        return MyResponse(request, {'status': 'ok', 'message': 'Successful'}, status=status.HTTP_200_OK)
