"""
Api module for the eccard app.
"""
from django.db import transaction
from django.db.models import Q
from django.contrib.auth import get_user_model

from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import BasicAuthentication
from rest_framework.authentication import SessionAuthentication

from feed.models import News
from cards.models import Card
from cards.models import CardMetadata

from .models import Notificaciones
from .serializer import InboxSerializer
from .serializer import NotificacionesSerializer


class AuthSession:  # pylint: disable=R0903
    """
    Use session authntication.
    """

    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)


class UsuariosList(AuthSession, APIView):
    """
    Endpoint to list users.
    """

    def get(self, request):
        """
        GET method handler.
        """
        data = []
        search = self.request.GET.get("term")
        usuarios_tarjetas_id = (
            CardMetadata.objects.filter(tarjeta__default=True)
            .values_list("tarjeta__usuario__id", flat=True)
            .extra(
                where=["UPPER(productos_servicios) like %s"],
                params=["%" + search.upper() + "%"],
            )
        )
        user_model = get_user_model()
        usuarios = user_model.objects.filter(
            Q(username__icontains=search)
            | Q(email__icontains=search)
            | Q(id__in=usuarios_tarjetas_id),
        ).exclude(id=self.request.user.id)[:10]
        for user in usuarios:
            data.append(
                {
                    "label": user.username,
                    "value": user.username,
                    "id": user.id,
                },
            )
        return Response(data)


class UsuariosListInbox(AuthSession, APIView):
    """
    Endpoint to list user inbox.
    """

    def get(self, request):
        """
        GET method handler.
        """
        data = []
        search = self.request.GET.get("term")
        usuarios_tarjetas_id = (
            CardMetadata.objects.filter(tarjeta__default=True)
            .values_list("tarjeta__usuario__id", flat=True)
            .extra(
                where=["UPPER(productos_servicios) like %s"],
                params=["%" + search.upper() + "%"],
            )
        )
        user_model = get_user_model()
        usuarios = user_model.objects.filter(
            Q(username__icontains=search)
            | Q(email__icontains=search)
            | Q(id__in=usuarios_tarjetas_id),
        ).exclude(id=self.request.user.id)[:10]
        for user in usuarios:
            data.append(
                {
                    "label": user.username,
                    "value": user.username,
                    "id": user.id,
                },
            )
        return Response(data)


class NotificacionesApi(AuthSession, generics.ListAPIView):
    """
    Endpoint to list notifications.
    """

    queryset = Notificaciones.objects.all().order_by("-id")
    serializer_class = NotificacionesSerializer

    def get_queryset(self):
        queryset = Notificaciones.objects.filter(
            user_to=self.request.user,
            visto=False,
        ).order_by("-id")[:5]
        return queryset


class InboxApi(AuthSession, generics.ListAPIView):
    """
    Endpoint to list notifications.
    """

    serializer_class = InboxSerializer

    def get_queryset(self):
        queryset = self.request.user.inbox.filter(has_unread=True).all()[:5]
        return queryset


class ShareTarjetaApi(AuthSession, APIView):
    """
    Endpoint to share a card.
    """

    @transaction.atomic()
    def get(self, request):
        """
        GET methods handler.
        """
        tarjeta = self.request.GET.get("tarjeta")
        comment_id = self.request.GET.get("comment")
        noticia = News()
        if tarjeta:
            try:
                tarjeta_compartir = Card.objects.get(id=tarjeta)
            except Card.DoesNotExist:
                return Response({"status": False})
            comment = "¡Hey miren esto...!"
            noticia.image = tarjeta_compartir.image

        if comment_id:
            try:
                comment_share = News.objects.get(id=comment_id)
            except comment_share.DoesNotExist:
                return Response({"status": False})
            comment = comment_share
            if comment_share.image:
                noticia.image = comment_share.image

        noticia.comment = comment
        noticia.user = self.request.user
        noticia.shared = True
        noticia.save()
        return Response({"status": True})
