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

from api.utils import get_graphql_mutation
from core.factories import UserFactory
from users.factories import SchoolClassFactory
from users.models import SchoolClass, User, SchoolClassMember
from api.schema import schema
from users.services import create_users


class JoinSchoolClassTest(TestCase):
    def setUp(self):
        self.client = Client(schema=schema)
        self.school_class_name = 'Moordale'

        user_data = [
            {
                'teacher': ('Emily', 'Sands',),
                'class': self.school_class_name,
                'code': 'SEXED',
                'students': [
                    ('Otis', 'Milburn'),
                    ('Maeve', 'Wiley'),
                    ('Adam', 'Groff'),
                    ('Eric', 'Effiong'),
                    ('Jackson', 'Marchetti'),
                ]
            },
            {
                'teacher': ('Colin', 'Hendricks'),
                'class': 'Swing Band',
                'students': [
                    ('Ola', 'Nyman'),
                ]
            }
        ]
        create_users(user_data)
        teacher = User.objects.get(username='emily.sands')
        self.teacher_id = to_global_id('PublicUserNode', teacher.pk)
        student = User.objects.get(username='adam.groff')
        self.student_id = to_global_id('PublicUserNode', student.pk)
        other_student = User.objects.get(username='eric.effiong')
        self.other_student_id = to_global_id('PublicUserNode', other_student.pk)

        school_class = SchoolClass.objects.get(name=self.school_class_name)
        self.school_class_id = to_global_id('SchoolClassNode', school_class.pk)
        self.teacher_context = Context(user=teacher)
        self.student_context = Context(user=student)

        self.mutation = get_graphql_mutation('addRemoveMember.gql')

    def test_leave_and_join_class(self):
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(),
            0)
        result = self.client.execute(self.mutation, variables={
            'input': {
                'schoolClass': self.school_class_id,
                'member': self.student_id,
                'active': False
            }
        }, context=self.teacher_context)
        self.assertIsNone(result.get('errors'))
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 5)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(),
            1)

        result = self.client.execute(self.mutation, variables={
            'input': {
                'schoolClass': self.school_class_id,
                'member': self.student_id,
                'active': True
            }
        }, context=self.teacher_context)

        self.assertIsNone(result.get('errors'))
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(),
            0)

    def test_leave_class_student_raises_error(self):
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)
        result = self.client.execute(self.mutation, variables={
            'input': {
                'schoolClass': self.school_class_id,
                'member': self.other_student_id,
                'active': False
            }
        }, context=self.student_context)
        self.assertIsNotNone(result['errors'])
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)

    def test_leave_class_other_school_class_raises_error(self):
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)
        student = User.objects.get(username='ola.nyman')
        school_class = SchoolClass.objects.get(name='Swing Band')
        result = self.client.execute(self.mutation, variables={
            'input': {
                'schoolClass': to_global_id('SchoolClassNode', school_class.id),
                'member': to_global_id('PublicUserNode', student.id),
                'active': False
            }
        }, context=self.teacher_context)
        self.assertIsNotNone(result['errors'])
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
        self.assertEqual(
            SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)
