from django.shortcuts import render
from django.http import JsonResponse
from django.db.models import Q
from django.contrib.auth import models as auth_models
from django.core.cache import cache
from rest_framework import viewsets, permissions, settings
from rest_framework.decorators import api_view, action
from rest_framework.response import Response

from api import serializers, models
from sde import serializers as sde_serializers, models as sde_models


class LoggedUserOnly:
    permission_classes = [permissions.IsAuthenticated]
    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = auth_models.User.objects.all().order_by('-date_joined')
    serializer_class = serializers.UserSerializer
    permission_classes = [permissions.IsAuthenticated]



class GroupViewSet(viewsets.ReadOnlyModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = auth_models.Group.objects.all()
    serializer_class = serializers.GroupSerializer
    permission_classes = [permissions.IsAuthenticated]


class AcquisitionViewSet(LoggedUserOnly, viewsets.ModelViewSet):
    """
    API endpoint that allows acquisitions to be viewed or edited.
    """
    queryset = models.Acquisition.objects.all().order_by('-date')
    serializer_class = serializers.AcquisitionSerializer


class TypeTrackingViewSet(LoggedUserOnly, viewsets.ModelViewSet):
    """
    API endpoint that allows types tracking to be viewed or edited.
    """
    queryset = models.TypeTracking.objects.all()
    serializer_class = serializers.TypeTrackingSerializer


@api_view(['POST'])
def custom_types_search(request):
    cache_key = f"custom_types_search_{request.data}"
    items = cache.get(cache_key, [])

    if not items:
        for q in request.data:
            conditions = Q()
            for k in q.keys():
                value = q[k]

                token = k.split('___')
                key, mods = token[0], token[1:]

                cond = Q(**{key: value})

                if "not" in mods:
                    cond = ~cond

                conditions = conditions & cond

            items.extend(sde_models.SDEType.objects.filter(conditions))
        cache.set(cache_key, items, 60 * 60)

    paginator = settings.api_settings.DEFAULT_PAGINATION_CLASS()
    result_page = paginator.paginate_queryset(items, request)
    serializer = sde_serializers.SDETypeSerializer(result_page, many=True)
    return paginator.get_paginated_response(serializer.data)


@api_view(['POST'])
def reprocess_eval(request):
    ep_mat = request.data.get("ep_mat")
    ep_items = request.data.get("ep_items")
    efficiency = request.data.get("efficiency", 0.55)

    matprices = {item["typeID"]: {'sell': item["prices"]["sell"]["min"], 'buy': item["prices"]["buy"]["max"]} for item in ep_mat['items']}

    item_reprocess = []
    for rawitem in ep_items["items"]:
        item = sde_models.SDEType.objects.get(id=rawitem["typeID"])
        buy_reprocess = sell_reprocess = 0.0
        for mat in item.typematerials.all():
            try:
                buy_reprocess += matprices[mat.material_type_id]['buy'] * mat.quantity/item.portionSize * efficiency
                sell_reprocess += matprices[mat.material_type_id]['sell'] * mat.quantity/item.portionSize * efficiency
            except KeyError as e:
                JsonResponse({"error": f"No price for material {e}"})
        item_reprocess.append({
            "typeID": item.id,
            "name": item.name,
            "buy": rawitem["prices"]['buy']["max"],
            "sell": rawitem["prices"]['sell']["min"],
            "buy_reprocess": buy_reprocess,
            "sell_reprocess": sell_reprocess,
        })

    paginator = settings.api_settings.DEFAULT_PAGINATION_CLASS()
    result_page = paginator.paginate_queryset(item_reprocess, request)
    return paginator.get_paginated_response(result_page)
