import json
from datetime import date

from django.http import JsonResponse
from django.views.generic import CreateView, ListView, UpdateView, View

from apps.core.permissions.mixins import RimsAccessMixin
from apps.core.permissions.roles import UserRole
from apps.rims.calendar.forms import CalendarEventForm
from apps.rims.calendar.models import CalendarEvent


class CalendarAccessMixin(RimsAccessMixin):
    allowed_roles = tuple(r.value for r in UserRole)


class CalendarAdminMixin(RimsAccessMixin):
    allowed_roles = (UserRole.ADMIN, UserRole.GRANTS_MANAGER, UserRole.PROGRAMME_OFFICER)


class CalendarView(CalendarAccessMixin, ListView):
    model = CalendarEvent
    template_name = "calendar/calendar.html"
    context_object_name = "events"

    def get_queryset(self):
        return CalendarEvent.objects.filter(visibility=CalendarEvent.Visibility.PUBLIC)

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["today"] = date.today()
        return ctx


class CalendarEventListView(CalendarAccessMixin, ListView):
    model = CalendarEvent
    template_name = "calendar/event_list.html"
    context_object_name = "events"
    paginate_by = 20

    def get_queryset(self):
        qs = CalendarEvent.objects.all()
        event_type = self.request.GET.get("type")
        if event_type:
            qs = qs.filter(event_type=event_type)
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["type_choices"] = CalendarEvent.EventType.choices
        return ctx

    def get_template_names(self):
        if getattr(self.request, "htmx", False):
            return ["calendar/partials/event_list_results.html"]
        return super().get_template_names()


class CalendarEventCreateView(CalendarAdminMixin, CreateView):
    model = CalendarEvent
    form_class = CalendarEventForm
    template_name = "calendar/event_form.html"

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_calendar:event_list")


class CalendarEventUpdateView(CalendarAdminMixin, UpdateView):
    model = CalendarEvent
    form_class = CalendarEventForm
    template_name = "calendar/event_edit.html"

    def get_success_url(self):
        from django.urls import reverse
        return reverse("rims_calendar:event_list")


class CalendarFeedView(CalendarAccessMixin, View):
    """JSON feed for FullCalendar or similar JS calendar libraries."""

    def get(self, request):
        qs = CalendarEvent.objects.filter(visibility=CalendarEvent.Visibility.PUBLIC)
        start = request.GET.get("start")
        end = request.GET.get("end")
        if start:
            qs = qs.filter(end_datetime__gte=start)
        if end:
            qs = qs.filter(start_datetime__lte=end)
        events = [
            {
                "id": e.pk,
                "title": e.title,
                "start": e.start_datetime.isoformat(),
                "end": e.end_datetime.isoformat(),
                "allDay": e.all_day,
                "extendedProps": {
                    "type": e.event_type,
                    "location": e.location,
                },
            }
            for e in qs
        ]
        return JsonResponse(events, safe=False)
