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

from rest_framework import status, viewsets
from rest_framework.test import APIRequestFactory, APITestCase

from ..mixins import SoftDestroyModelMixin

from .api_testapp.factories import NonSyncableModelFactory, SyncableModelFactory
from .api_testapp.models import NonSyncableModel, SyncableModel
from .api_testapp.serializers import NonSyncableModelSerializer, SyncableModelSerializer


class SoftDestroyModelMixinTestCase(APITestCase):
    """Test case for the ``SoftDestroyModelMixin`` mixin."""

    class SyncableModelViewSet(SoftDestroyModelMixin, viewsets.ModelViewSet):
        """The viewset for syncable instances."""

        queryset = SyncableModel.objects.non_deleted()
        serializer_class = SyncableModelSerializer

    class NonSyncableModelViewSet(SoftDestroyModelMixin, viewsets.ModelViewSet):
        """The viewset for non syncable instances."""

        queryset = NonSyncableModel.objects.all()
        serializer_class = NonSyncableModelSerializer

    @classmethod
    def setUpTestData(cls):
        """Create a request factory and instances to test."""

        super().setUpTestData()

        cls.factory = APIRequestFactory()
        cls.syncable_instance = SyncableModelFactory()
        cls.non_syncable_instance = NonSyncableModelFactory()

    def test_soft_delete_syncable_instance(self):
        """Test the soft deletion of syncable instance through an api call."""

        # The instance shouldn't be soft-deleted
        self.assertFalse(self.syncable_instance.is_deleted)

        request = self.factory.delete('/users/%s/' % self.syncable_instance.pk)
        view = self.SyncableModelViewSet.as_view({'delete': 'destroy'})

        response = view(request, pk=self.syncable_instance.pk)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

        # The instance should be soft-deleted
        self.syncable_instance.refresh_from_db()
        self.assertTrue(self.syncable_instance.is_deleted)

    def test_delete_non_syncable_instance(self):
        """Test the deletion of non syncable instance through an api call."""

        request = self.factory.delete('/users/%s/' % self.non_syncable_instance.pk)
        view = self.NonSyncableModelViewSet.as_view({'delete': 'destroy'})

        response = view(request, pk=self.non_syncable_instance.pk)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

        # The instance should be delete
        with self.assertRaises(NonSyncableModel.DoesNotExist):
            self.non_syncable_instance.refresh_from_db()
