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

from api.schema import schema
from api.utils import get_graphql_mutation, get_object
from core.factories import UserFactory, TeacherFactory
from core.tests.base_test import SkillboxTestCase
from users.models import SchoolClass, User
from users.services import create_users

UPDATE_SCHOOL_CLASS_MUTATION = get_graphql_mutation('updateSchoolClass.gql')


class SchoolClassesTest(TestCase):

    def setUp(self):
        self.prefix = 'Meine Klasse'

    def test_default_class_name_initial(self):
        class_name = SchoolClass.generate_default_group_name()
        self.assertEqual('{} 1'.format(self.prefix), class_name)

    def test_default_class_name_initial_with_similar_existing(self):
        SchoolClass.objects.create(name='{} abc212'.format(self.prefix))
        class_name = SchoolClass.generate_default_group_name()
        self.assertEqual('{} 1'.format(self.prefix), class_name)

    def test_default_class_name_if_existing(self):
        SchoolClass.objects.create(name='{} 1'.format(self.prefix))
        SchoolClass.objects.create(name='{} 10'.format(self.prefix))
        class_name = SchoolClass.generate_default_group_name()
        self.assertEqual('{} 11'.format(self.prefix), class_name)

    def test_default_class_name_with_user(self):
        user = UserFactory(username='hansli')
        class_name = SchoolClass.generate_default_group_name(user=user)
        self.assertEqual(f'{self.prefix} {user.pk}', class_name)


class ModifySchoolClassTest(SkillboxTestCase):
    def setUp(self):
        create_users()
        self.teacher = User.objects.get(username='teacher')
        self.student = User.objects.get(username='student1')

        self.client = self.get_client(user=self.teacher)
        self.student_client = self.get_client(user=self.student)

    def test_update_school_class(self):
        class_name = 'The Colbert Show'

        school_class = SchoolClass.objects.get(name='skillbox')
        self.assertEqual(school_class.name, 'skillbox')
        id = to_global_id('SchoolClassNode', school_class.id)

        result = self.client.execute(UPDATE_SCHOOL_CLASS_MUTATION, variables={
            'input': {
                'id': id,
                'name': class_name
            }
        })
        self.assertIsNone(result.get('errors'))

        school_class = get_object(SchoolClass, id)
        self.assertEqual(school_class.name, class_name)

    def test_update_school_class_not_in_class_fails(self):
        client = Client(schema=schema)
        teacher = TeacherFactory(username='conan')
        context = Context(user=teacher)
        school_class = SchoolClass.objects.get(name='skillbox')
        self.assertEqual(school_class.name, 'skillbox')
        id = to_global_id('SchoolClassNode', school_class.id)
        variables = {
            'input': {
                'id': id,
                'name': 'Nein'
            }
        }
        result = client.execute(UPDATE_SCHOOL_CLASS_MUTATION, variables=variables, context=context)
        self.assertIsNone(result.get('errors'))

    def test_update_school_class_fail(self):
        class_name = 'Nanana'

        school_class = SchoolClass.objects.get(name='skillbox')
        self.assertEqual(school_class.name, 'skillbox')
        id = to_global_id('SchoolClassNode', school_class.id)

        result = self.student_client.execute(UPDATE_SCHOOL_CLASS_MUTATION, variables={
            'input': {
                'id': id,
                'name': class_name
            }
        })
        self.assertIsNotNone(result.get('errors'))

    def test_create_school_class(self):
        self.assertEqual(SchoolClass.objects.count(), 2)
        class_name = 'Moordale'
        mutation = get_graphql_mutation('createClass.gql')
        result = self.client.execute(mutation, variables={
            'input': {
                'name': class_name
            }
        })
        self.assertIsNone(result.get('errors'))
        id = result.get('data').get('createSchoolClass').get('schoolClass').get('id')
        self.assertEqual(SchoolClass.objects.count(), 3)
        school_class = get_object(SchoolClass, id)
        self.assertEqual(school_class.name, class_name)
        self.assertEqual(school_class.get_teacher(), self.teacher)
        self.assertEqual(self.teacher.selected_class.name, class_name)

    def test_create_school_class_fail(self):
        self.assertEqual(SchoolClass.objects.count(), 2)
        mutation = get_graphql_mutation('createClass.gql')
        result = self.student_client.execute(mutation, variables={
            'input': {
                'name': 'No School'
            }
        })
        self.assertIsNotNone(result.get('errors'))
