from django.test import TestCase, RequestFactory
from graphene.test import Client
from graphql_relay import to_global_id

from api.schema import schema
from api.utils import get_object
from books.models import ContentBlock, Chapter
from books.factories import ModuleFactory, BookFactory
from core.factories import UserFactory
from users.services import create_users


class RecentModulesTest(TestCase):
    def setUp(self):
        create_users()
        _, topic, self.module1, chapter, _ = BookFactory.create_default_structure()

        self.modules = []
        for i in range(1, 5):
            module = ModuleFactory.create(parent=topic,
                                          title=f"Another module {i}",
                                          meta_title=f"Modul {i}",
                                          teaser="Whatever",
                                          intro="<p>Hello</p>")
            self.modules.append(module)

        user = UserFactory(username='aschi')

        request = RequestFactory().get('/')
        request.user = user
        self.client = Client(schema=schema, context_value=request)

    def _update_last_module(self, module):
        mutation = """
        mutation UpdateLastModule($input: UpdateLastModuleInput!) {
          updateLastModule(input: $input) {
            lastModule {
              id
            }
          }
        }
        """

        result = self.client.execute(mutation, variables={
            'input': {
                'id': to_global_id('ModuleNode', module.id)
            }
        })
        self.assertIsNone(result.get('errors'))

    def _get_recent_modules(self):
        recent_modules_query = """
                query RecentModulesQuery {
                    me {
                        recentModules(orderBy: "-visited") {
                            edges {
                              node {
                                id
                                title
                              }
                            }
                        }
                    }
                }
                """

        return list(map(lambda x: x['node'], self.client.execute(recent_modules_query).get('data').get('me').get('recentModules').get('edges')))

    def test_no_recent_modules(self):
        edges = self._get_recent_modules()

        self.assertEqual(len(edges), 0)

    def test_update_last_module(self):
        self._update_last_module(self.module1)

    def test_recent_modules(self):
        module1, module2, module3, module4 = self.modules

        self._update_last_module(module1)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 1)
        self.assertEqual(recent_modules[0].get('title'), module1.title)

        # same module twice
        self._update_last_module(module1)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 1)

        self._update_last_module(module2)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 2)
        self.assertEqual(recent_modules[0].get('title'), module2.title)
        self.assertEqual(recent_modules[1].get('title'), module1.title)

        # same module as before again
        self._update_last_module(module1)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 2)
        self.assertEqual(recent_modules[0].get('title'), module1.title)
        self.assertEqual(recent_modules[1].get('title'), module2.title)


        self._update_last_module(module3)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 3)
        self.assertEqual(recent_modules[0].get('title'), module3.title)
        self.assertEqual(recent_modules[1].get('title'), module1.title)
        self.assertEqual(recent_modules[2].get('title'), module2.title)

        self._update_last_module(module4)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 3)
        self.assertEqual(recent_modules[0].get('title'), module4.title)
        self.assertEqual(recent_modules[1].get('title'), module3.title)
        self.assertEqual(recent_modules[2].get('title'), module1.title)

        # same again
        self._update_last_module(module4)
        recent_modules = self._get_recent_modules()
        self.assertEqual(len(recent_modules), 3)
        self.assertEqual(recent_modules[0].get('title'), module4.title)
        self.assertEqual(recent_modules[1].get('title'), module3.title)
        self.assertEqual(recent_modules[2].get('title'), module1.title)


