import datetime

from django.shortcuts import render
from django.utils.timezone import now, localtime
from rest_framework import authentication, permissions, status, viewsets
import rest_framework.generics
from rest_framework.response import Response
from rest_framework.views import APIView

import recipe.models
import recipe.serializers
from utils import const


class RecipeAPI(viewsets.ModelViewSet):

    # authentication_classes = (authentication.TokenAuthentication,
    #                           authentication.SessionAuthentication,
    #                           authentication.BasicAuthentication)
    # permission_classes = (permissions.IsAuthenticated,)
    queryset = recipe.models.Recipe.objects.all()
    serializer_class = recipe.serializers.RecipeSerializer

    def perform_destroy(self, instance):
        instance.status = const.RECIPE_STATUS_DELETED
        instance.save(update_fields=['status'])

    def perform_update(self, serializer):
        instance = self.get_object()
        if 'recipe_ingredients' in self.request.data:
            recipe_ingredients = self.request.data.pop('recipe_ingredients')
            if recipe_ingredients:
                for recipe_ingredient in recipe_ingredients:
                    # 没有 id 则新增食材
                    if not recipe_ingredient['id'] and recipe_ingredient['quantity']:
                        ingredient = recipe.models.Ingredient.objects.get(id=recipe_ingredient['ingredient']['id'])
                        del recipe_ingredient['ingredient']
                        del recipe_ingredient['id']
                        recipe.models.RecipeIngredient.objects.create(
                            recipe=instance, ingredient=ingredient, **recipe_ingredient
                        )
                    # 有 id 没数量则删除食材
                    elif recipe_ingredient['id'] and not recipe_ingredient['quantity']:
                        recipe.models.RecipeIngredient.objects.filter(id=recipe_ingredient['id']).update(
                            status=const.INGREDIENT_STATUS_DELETED
                        )
                    # 有 id 有数量则更新食材
                    elif recipe_ingredient['id'] and recipe_ingredient['quantity']:
                        del recipe_ingredient['ingredient']
                        recipe.models.RecipeIngredient.objects.filter(id=recipe_ingredient['id']).update(
                            **recipe_ingredient
                        )

        return super().perform_update(serializer)

    def list(self, request, *args, **kwargs):
        self.queryset = recipe.models.Recipe.objects.exclude(status=const.RECIPE_STATUS_DELETED)
        return super().list(request, *args, **kwargs)

    filterset_fields = {
        'recipe_type': const.FILTER_EXACT,
        'difficulty': const.FILTER_GTE_LTE,
        'rate': const.FILTER_GTE_LTE,
    }


class WeekRecipeListAPI(rest_framework.generics.ListCreateAPIView):

    queryset = recipe.models.DailyRecipe.objects.all()
    serializer_class = recipe.serializers.WeekRecipeSerializer

    def post(self, request, *args, **kwargs):
        # Monday == 0 ... Sunday == 6
        today = localtime()
        recipes = []
        for x in range(0, 7 - today.weekday()):
            daily_recipe, __ = recipe.models.DailyRecipe.objects.get_or_create(date=today + datetime.timedelta(days=x))
            daily_recipe.generate_recipe(recipes)
            recipes.extend(daily_recipe.recipes.values_list('id', flat=True))
        return Response(recipe.models.DailyRecipe.get_week_recipe_data(), status=status.HTTP_201_CREATED, headers={})

    def get(self, request, *args, **kwargs):
        data = recipe.models.DailyRecipe.get_week_recipe_data()
        return Response(data)


class DailyRecipeAPI(rest_framework.generics.RetrieveUpdateAPIView):

    queryset = recipe.models.DailyRecipe.objects.all()
    serializer_class = recipe.serializers.DailyRecipeSerializer

    def post(self, request, *args, **kwargs):
        daily_recipe = recipe.models.DailyRecipe.objects.get(id=kwargs['pk'])
        daily_recipe.generate_recipe()
        return Response(daily_recipe.serialize(), status=status.HTTP_201_CREATED, headers={})

    def put(self, request, *args, **kwargs):
        daily_recipe = recipe.models.DailyRecipe.objects.get(id=kwargs['pk'])
        recipes = request.data.get('meat', [])
        recipes.extend(request.data.get('vegetable', []))
        recipes.extend(request.data.get('soup', []))
        daily_recipe.recipes.set(recipe.models.Recipe.objects.filter(id__in=recipes))
        return Response(daily_recipe.serialize(), status=status.HTTP_201_CREATED, headers={})


class IngredientAPI(viewsets.ModelViewSet):

    # authentication_classes = (authentication.TokenAuthentication,
    #                           authentication.SessionAuthentication,
    #                           authentication.BasicAuthentication)
    # permission_classes = (permissions.IsAuthenticated,)
    queryset = recipe.models.Ingredient.objects.all()
    serializer_class = recipe.serializers.IngredientSerializer

    def list(self, request, *args, **kwargs):
        self.queryset = recipe.models.Ingredient.objects.exclude(status=const.INGREDIENT_STATUS_DELETED).order_by('-id')
        return super().list(request, *args, **kwargs)

    def perform_destroy(self, instance):
        instance.status = const.INGREDIENT_STATUS_DELETED
        instance.save(update_fields=['status'])


class RecipeIngredientAPI(viewsets.ModelViewSet):

    # authentication_classes = (authentication.TokenAuthentication,
    #                           authentication.SessionAuthentication,
    #                           authentication.BasicAuthentication)
    # permission_classes = (permissions.IsAuthenticated,)
    queryset = recipe.models.RecipeIngredient.objects.exclude(status=const.INGREDIENT_STATUS_DELETED)
    serializer_class = recipe.serializers.RecipeIngredientSerializer

    def get_queryset(self):
        return self.queryset.filter(recipe=self.kwargs['recipe_pk'])

    def perform_destroy(self, instance):
        instance.status = const.INGREDIENT_STATUS_DELETED
        instance.save(update_fields=['status'])

    def create(self, request, *args, **kwargs):
        recipe_ingredient = recipe.models.RecipeIngredient.objects.create(
            recipe_id=kwargs['recipe_pk'], ingredient_id=request.data['ingredient'], quantity=request.data['quantity']
        )
        return Response(recipe_ingredient.serialize(), status=status.HTTP_201_CREATED, headers={})
