"""This module holds viewsets tests for ``likes`` app."""

from rest_framework.test import APIRequestFactory

from mtp.apps.api.tests.test_cases import MTPAPITestCase
from mtp.apps.likes.models import Like
from mtp.apps.likes.tests.likeable_testapp.models import Proposition
from mtp.apps.likes.tests.likeable_testapp.serializers import PropositionSerializer

from ..viewsets import LikeableViewSet


class LikeableViewSetTestCase(MTPAPITestCase):
    """Test case for ``LikeableViewSet`` viewset."""

    class PropositionViewSet(LikeableViewSet):
        """The viewset to test."""

        queryset = Proposition.objects.non_deleted()
        serializer_class = PropositionSerializer

    @classmethod
    def setUpTestData(cls):
        """Prepare some data for tests."""

        super().setUpTestData()

        cls.factory = APIRequestFactory()
        cls.proposition = Proposition.objects.create(text='fake_proposition')

    @staticmethod
    def get_likes(user):
        """Return the current like for the provided user.

        Parameters
        ----------
        user: User
            The user who created these likes.

        """

        return Like.objects.filter(author=user).non_deleted()

    def test_create_likes(self):
        """Test the like end point."""

        # We check we have no like for this trainee
        self.assertEqual(len(self.get_likes(self.trainee)), 0)

        request = self.factory.post('propositions/likes')
        request.user = self.trainee

        # The trainee likes the proposition
        viewset = self.PropositionViewSet.as_view({'post': 'likes'})
        response = viewset(request, pk=self.proposition.pk)

        # We should have one like for this trainee
        likes = self.get_likes(self.trainee)
        self.assertEqual(len(self.get_likes(self.trainee)), 1)
        like = likes.first()
        self.assertEqual(like.author.pk, self.trainee.pk)
        self.assertEqual(response.data['author'], self.trainee.pk)
        self.assertEqual(like.liked_object.id, self.proposition.id)

    def test_delete_likes(self):
        """Test the unlike end point."""

        self.trainee.like(self.proposition)

        # We should have one like for this trainee
        self.assertEqual(len(self.get_likes(self.trainee)), 1)

        request = self.factory.delete('propositions/likes')
        request.user = self.trainee

        # The trainee unlikes the proposition
        viewset = self.PropositionViewSet.as_view({'delete': 'likes'})
        viewset(request, pk=self.proposition.pk)

        # Now, we should have no like for this trainee
        self.assertEqual(len(self.get_likes(self.trainee)), 0)
