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, get_graphql_mutation
from books.models import ContentBlock, Chapter
from books.factories import ModuleFactory
from core.factories import UserFactory
from notes.factories import ChapterBookmarkFactory, ModuleBookmarkFactory
from notes.models import Note, ModuleBookmark, ChapterBookmark


class NoteMutationTestCase(TestCase):
    def setUp(self):
        self.module = ModuleFactory()
        self.chapter = Chapter(title='Hello')
        self.module.add_child(instance=self.chapter)
        self.user = user = UserFactory(username='aschi')
        content_block = ContentBlock(title='bla', slug='bla')
        self.chapter.specific.add_child(instance=content_block)
        ChapterBookmarkFactory.create(chapter=self.chapter, user=user)
        ModuleBookmarkFactory.create(module=self.module, user=user)

        request = RequestFactory().get('/')
        request.user = user

        self.client = Client(schema=schema, context_value=request)
        self.add_mutation = get_graphql_mutation('addNote.gql')
        self.update_mutation = get_graphql_mutation('updateNote.gql')


class NewNoteMutationTestCase(NoteMutationTestCase):
    def test_add_chapter_note(self):
        self.assertEqual(Note.objects.count(), 0)
        text = 'Hello World'
        result = self.client.execute(self.add_mutation, variables={
            'input': {
                'note': {
                    'parent': to_global_id('ChapterNode', self.chapter.pk),
                    'text': text
                }
            }
        })
        self.assertIsNone(result.get('errors'))

        self.assertEqual(Note.objects.count(), 1)
        self.assertEqual(Note.objects.first().text, text)

    def test_add_module_note(self):
        self.assertEqual(Note.objects.count(), 0)
        text = 'Hello World'
        result = self.client.execute(self.add_mutation, variables={
            'input': {
                'note': {
                    'parent': to_global_id('ModuleNode', self.module.pk),
                    'text': text
                }
            }
        })
        self.assertIsNone(result.get('errors'))

        self.assertEqual(Note.objects.count(), 1)
        self.assertEqual(Note.objects.first().text, text)


class UpdateNoteMutationTestCase(NoteMutationTestCase):
    def setUp(self):
        super(UpdateNoteMutationTestCase, self).setUp()

        self.chapter_note = Note.objects.create(text='Hello World')
        self.module_note = Note.objects.create(text='Hello World')

        self.chapter_bookmark = ChapterBookmark.objects.get(user=self.user, chapter=self.chapter)
        self.chapter_bookmark.note = self.chapter_note
        self.chapter_bookmark.save()

        self.module_bookmark = ModuleBookmark.objects.get(user=self.user, module=self.module)
        self.module_bookmark.note = self.module_note
        self.module_bookmark.save()

    def test_change_module_note(self):
        self.assertEqual(Note.objects.count(), 2)
        self.assertEqual(self.module_bookmark.note.text, 'Hello World')

        new_text = 'Salut monde'
        result = self.client.execute(self.update_mutation, variables={
            'input': {
                'note': {
                    'id': to_global_id('NoteNode', self.module_bookmark.note.pk),
                    'text': new_text
                }
            }
        })
        self.assertIsNone(result.get('errors'))

        bookmark = ModuleBookmark.objects.get(user=self.user, module=self.module)
        self.assertEqual(bookmark.note.text, new_text)

        self.assertEqual(Note.objects.count(), 2)

    def test_change_chapter_note(self):
        self.assertEqual(Note.objects.count(), 2)
        self.assertEqual(self.chapter_bookmark.note.text, 'Hello World')

        new_text = 'Salut monde'
        result = self.client.execute(self.update_mutation, variables={
            'input': {
                'note': {
                    'id': to_global_id('NoteNode', self.chapter_bookmark.note.pk),
                    'text': new_text
                }
            }
        })
        self.assertIsNone(result.get('errors'))

        bookmark = ChapterBookmark.objects.get(user=self.user, chapter=self.chapter)
        self.assertEqual(bookmark.note.text, new_text)

        self.assertEqual(Note.objects.count(), 2)

    def test_update_wrong_user(self):
        godis_note = Note.objects.create(text='Hello Godi')
        godi = UserFactory(username='godi')
        godis_bookmark = ModuleBookmarkFactory(module=self.module, user=godi)

        godis_bookmark.note = godis_note
        godis_bookmark.save()

        result = self.client.execute(self.update_mutation, variables={
            'input': {
                'note': {
                    'id': to_global_id('NoteNode', godis_note.pk),
                    'text': 'Hello Aschi'
                }
            }
        })
        print(result.get('errors'))
        self.assertIsNotNone(result.get('errors'))
