"""
Views model for the chat app.
"""
from django.http import Http404
from django.utils import timezone
from django.db.models import Q
from django.db.models import OuterRef
from django.db.models import Subquery
from django.views.generic import View
from django.views.generic import DetailView
from django.views.generic import TemplateView

from users.models import User

from .models import Inbox
from .models import Message


class InboxListMixin(View):
    """
    Get the inbox list for the current user.
    """

    def get_context_data(self, **kwargs):
        """
        Set the inbox list for the current user in the view context.
        """
        context = super().get_context_data(**kwargs)

        user = self.request.user

        messages_subquery = Message.objects.filter(
            Q(sender=user, recipient=OuterRef("sender_id"))
            | Q(sender=OuterRef("sender_id"), recipient=user),
        ).order_by("-created")
        context["inbox_list"] = (
            user.inbox.prefetch_related(
                "sender",
            )
            .annotate(
                last_message_time=Subquery(
                    messages_subquery.values("created")[:1],
                ),
                last_message_content=Subquery(
                    messages_subquery.values("content")[:1],
                ),
            )
            .order_by("-last_message_time")
            .filter(last_message_time__isnull=False)
            .all()
        )

        return context


class InboxView(InboxListMixin, TemplateView):
    """
    Display the inbox list.
    """

    template_name = "chat/inbox_list.html"


class InboxDetailView(InboxListMixin, DetailView):
    """
    Display the chats list or selected chat.
    """

    model = Inbox

    def get_queryset(self):
        return (
            self.request.user.inbox.prefetch_related("messages")
            .prefetch_related("messages__sender")
            .prefetch_related("sender")
        )

    def get_object(self, queryset=None):
        if queryset is None:
            queryset = self.get_queryset()

        pk = self.kwargs.get(self.pk_url_kwarg)  # pylint: disable=C0103
        try:
            user = User.objects.get(pk=pk)
            inbox = queryset.get(sender_id=pk)
        except User.DoesNotExist as missing_user:
            raise Http404() from missing_user
        except queryset.model.DoesNotExist:
            inbox = self.model.objects.create(
                owner=self.request.user,
                sender=user,
            )

        if inbox.has_unread:
            unread_messages = (
                inbox.messages.filter(sender=inbox.sender)
                .filter(read_at__isnull=True)
                .all()
            )
            unread_messages.update(read_at=timezone.now())
            inbox.has_unread = False
            inbox.save()

        return inbox
