from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.utils import timezone
from django.views.generic import ListView
from rest_framework import viewsets, mixins, serializers, permissions

from AKModel.availability.models import Availability
from AKModel.models import Room, AKSlot, ConstraintViolation
from AKModel.views import EventSlugMixin


class ResourceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Room
        fields = ['id', 'title']

    title = serializers.SerializerMethodField('transform_title')

    def transform_title(self, obj):
        if obj.capacity > 0:
            return f"{obj.title} [{obj.capacity}]"
        return obj.title


class ResourcesViewSet(EventSlugMixin, mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
    permission_classes = (permissions.DjangoModelPermissionsOrAnonReadOnly,)
    serializer_class = ResourceSerializer

    def get_queryset(self):
        return Room.objects.filter(event=self.event)


class EventsView(LoginRequiredMixin, EventSlugMixin, ListView):
    model = AKSlot

    def get_queryset(self):
        return super().get_queryset().filter(event=self.event, room__isnull=False)

    def render_to_response(self, context, **response_kwargs):
        return JsonResponse(
            [{
                "slotID": slot.pk,
                "title": f'{slot.ak.short_name}: \n{slot.ak.owners_list}',
                "description": slot.ak.details,
                "resourceId": slot.room.id,
                "start": timezone.localtime(slot.start, self.event.timezone).strftime("%Y-%m-%d %H:%M:%S"),
                "end": timezone.localtime(slot.end, self.event.timezone).strftime("%Y-%m-%d %H:%M:%S"),
                "backgroundColor": slot.ak.category.color,
                "borderColor": "#2c3e50" if slot.fixed else '#e74c3c' if slot.constraintviolation_set.count() > 0 else slot.ak.category.color,
                "constraint": 'roomAvailable',
                "editable": not slot.fixed,
                'url': str(reverse('admin:AKModel_akslot_change', args=[slot.pk])),
            } for slot in context["object_list"]],
            safe=False,
            **response_kwargs
        )


class RoomAvailabilitiesView(LoginRequiredMixin, EventSlugMixin, ListView):
    model = Availability
    context_object_name = "availabilities"

    def get_queryset(self):
        return super().get_queryset().filter(event=self.event, room__isnull=False)

    def render_to_response(self, context, **response_kwargs):
        return JsonResponse(
            [{
                "title": "",
                "resourceId": a.room.id,
                "start": timezone.localtime(a.start, self.event.timezone).strftime("%Y-%m-%d %H:%M:%S"),
                "end": timezone.localtime(a.end, self.event.timezone).strftime("%Y-%m-%d %H:%M:%S"),
                "display": 'background',
                "groupId": 'roomAvailable',
            } for a in context["availabilities"]],
            safe=False,
            **response_kwargs
        )


class EventSerializer(serializers.ModelSerializer):
    class Meta:
        model = AKSlot
        fields = ['id', 'start', 'end', 'roomId']

    start = serializers.DateTimeField()
    end = serializers.DateTimeField()
    roomId = serializers.IntegerField(source='room.pk')

    def update(self, instance, validated_data):
        start = timezone.make_aware(timezone.make_naive(validated_data.get('start')), instance.event.timezone)
        end = timezone.make_aware(timezone.make_naive(validated_data.get('end')), instance.event.timezone)
        instance.start = start
        instance.room = get_object_or_404(Room, pk=validated_data.get('room')["pk"])
        diff = end - start
        instance.duration = round(diff.days * 24 + (diff.seconds / 3600), 2)
        instance.save()
        return instance


class EventsViewSet(EventSlugMixin, viewsets.ModelViewSet):
    permission_classes = (permissions.DjangoModelPermissions,)
    serializer_class = EventSerializer

    def get_object(self):
        return get_object_or_404(AKSlot, pk=self.kwargs["pk"])

    def get_queryset(self):
        return AKSlot.objects.filter(event=self.event)


class ConstraintViolationSerializer(serializers.ModelSerializer):
    class Meta:
        model = ConstraintViolation
        fields = ['pk', 'type_display', 'aks', 'ak_slots', 'ak_owner', 'room', 'requirement', 'category', 'comment', 'timestamp_display', 'manually_resolved', 'level_display', 'details', 'edit_url']


class ConstraintViolationsViewSet(EventSlugMixin, viewsets.ModelViewSet):
    permission_classes = (permissions.DjangoModelPermissions,)
    serializer_class = ConstraintViolationSerializer

    def get_object(self):
        return get_object_or_404(ConstraintViolation, pk=self.kwargs["pk"])

    def get_queryset(self):
        return ConstraintViolation.objects.filter(event=self.event).order_by('manually_resolved', '-type', '-timestamp')