import attr
import pytest
from django.test import TestCase
from rest_framework.test import APIRequestFactory

from mantle import Query
from mantle_drf.generics import GenericAPIView
from tests.models import Item


@attr.define
class ItemShape:
    name: str
    slug: str


factory = APIRequestFactory()


class TestGetShapeClass(TestCase):
    def test_get_shape_class_returns_shape_class(self):
        class TestView(GenericAPIView):
            shape_class = ItemShape

        view = TestView()
        assert view.get_shape_class() is ItemShape

    def test_get_shape_class_raises_without_shape_class(self):
        class TestView(GenericAPIView):
            pass

        view = TestView()
        with pytest.raises(AssertionError):
            view.get_shape_class()


class TestGetQuery(TestCase):
    def test_get_query_returns_query(self):
        class TestView(GenericAPIView):
            queryset = Item.objects.all()
            shape_class = ItemShape

        view = TestView()
        query = view.get_query()
        assert isinstance(query, Query)

    def test_get_query_with_custom_queryset(self):
        class TestView(GenericAPIView):
            queryset = Item.objects.all()
            shape_class = ItemShape

        view = TestView()
        qs = Item.objects.filter(name="test")
        query = view.get_query(queryset=qs)
        assert isinstance(query, Query)


class TestStructure(TestCase):
    def test_structure(self):
        class TestView(GenericAPIView):
            shape_class = ItemShape

        view = TestView()
        shape = view.structure({"name": "Test", "slug": "test"})
        assert isinstance(shape, ItemShape)
        assert shape.name == "Test"
        assert shape.slug == "test"


class TestUnstructure(TestCase):
    def test_unstructure(self):
        class TestView(GenericAPIView):
            shape_class = ItemShape

        view = TestView()
        shape = ItemShape(name="Test", slug="test")
        data = view.unstructure(shape)
        assert data == {"name": "Test", "slug": "test"}


class TestGetSerializerClass(TestCase):
    def test_get_serializer_class_returns_none(self):
        """We don't use serializers."""

        class TestView(GenericAPIView):
            shape_class = ItemShape

        view = TestView()
        assert view.get_serializer_class() is None
