from django.urls import path
from django.contrib.auth.decorators import permission_required
from rest_framework import routers, viewsets
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

from inventory.models import Event, Container, Item
from inventory.serializers import EventSerializer, ContainerSerializer, ItemSerializer


class EventViewSet(viewsets.ModelViewSet):
    serializer_class = EventSerializer
    queryset = Event.objects.all()
    permission_classes = []


class ContainerViewSet(viewsets.ModelViewSet):
    serializer_class = ContainerSerializer
    queryset = Container.objects.all()


@api_view(['GET'])
@permission_classes([IsAuthenticated])
@permission_required('view_item', raise_exception=True)
def search_items(request, event_slug, query):
    try:
        event = Event.objects.get(slug=event_slug)
        query_tokens = query.split(' ')
        q = Item.objects.filter(event=event)
        for token in query_tokens:
            if token:
                q = q.filter(description__icontains=token)
        return Response(ItemSerializer(q, many=True).data)
    except Event.DoesNotExist:
        return Response(status=404)


@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def item(request, event_slug):
    try:
        event = Event.objects.get(slug=event_slug)
        if request.method == 'GET':
            if not request.user.has_event_perm(event, 'view_item'):
                return Response(status=403)
            return Response(ItemSerializer(Item.objects.filter(event=event), many=True).data)
        elif request.method == 'POST':
            if not request.user.has_event_perm(event, 'add_item'):
                return Response(status=403)
            validated_data = ItemSerializer(data=request.data)
            if validated_data.is_valid():
                validated_data.save(event=event)
                return Response(validated_data.data, status=201)
    except Event.DoesNotExist:
        return Response(status=404)


@api_view(['GET', 'PUT', 'DELETE', 'PATCH'])
@permission_classes([IsAuthenticated])
def item_by_id(request, event_slug, id):
    try:
        event = Event.objects.get(slug=event_slug)
        item = Item.objects.get(event=event, uid=id)
        if request.method == 'GET':
            if not request.user.has_event_perm(event, 'view_item'):
                return Response(status=403)
            return Response(ItemSerializer(item).data)
        elif request.method == 'PUT':
            if not request.user.has_event_perm(event, 'change_item'):
                return Response(status=403)
            validated_data = ItemSerializer(item, data=request.data)
            if validated_data.is_valid():
                validated_data.save()
                return Response(validated_data.data)
            return Response(validated_data.errors, status=400)
        elif request.method == 'PATCH':
            if not request.user.has_event_perm(event, 'change_item'):
                return Response(status=403)
            validated_data = ItemSerializer(item, data=request.data, partial=True)
            if validated_data.is_valid():
                validated_data.save()
                return Response(validated_data.data)
            return Response(validated_data.errors, status=400)
        elif request.method == 'DELETE':
            if not request.user.has_event_perm(event, 'delete_item'):
                return Response(status=403)
            item.delete()
            return Response(status=204)
    except Item.DoesNotExist:
        return Response(status=404)
    except Event.DoesNotExist:
        return Response(status=404)


router = routers.SimpleRouter()
router.register(r'events', EventViewSet, basename='events')
router.register(r'boxes', ContainerViewSet, basename='boxes')
router.register(r'box', ContainerViewSet, basename='boxes')

urlpatterns = router.urls + [
    path('<event_slug>/items/', item),
    path('<event_slug>/items/<query>/', search_items),
    path('<event_slug>/item/', item),
    path('<event_slug>/item/<id>/', item_by_id),
]