from constance.test import override_config
from django.urls import reverse
from rest_framework import status
from rest_framework.test import (APIRequestFactory, APITestCase,
                                 force_authenticate)

from core import models
from core.views import StudentReviewerApiViewSet
from util.factories import make_test_data


class StudentPageTests(APITestCase):

    @classmethod
    def setUpTestData(cls):
        cls.factory = APIRequestFactory()

    def setUp(self):
        self.test_data = make_test_data(data_dict={
            'exams': [{
                'module_reference': 'TestExam B.Inf.0042',
                'total_score': 42,
                'pass_score': 21
            }],
            'submission_types': [{
                'name': 'problem01',
                'full_score': 10,
                'description': 'Very hard',
                'solution': 'Impossible!'
            }],
            'students': [
                {
                    'username': 'user01',
                    'exam': 'TestExam B.Inf.0042',
                    'exercise_groups': ['Group 01'],
                },
                {
                    'username': 'user02',
                    'exam': 'TestExam B.Inf.0042',
                    'exercise_groups': ['Group 02'],
                },
                {
                    'username': 'user03',
                    'exam': 'TestExam B.Inf.0042',
                    'exercise_groups': ['Group 02'],
                }
            ],
            'tutors': [{
                'username': 'tutor',
                'exercise_groups': ['Group 02'],
            }],
            'reviewers': [{
                'username': 'reviewer',
                'exercise_groups': ['Group 1337'],
            }],
            'submissions': [{
                'user': 'user01',
                'type': 'problem01',
                'text': 'Too hard for me ;-(',
                'feedback': {
                    'score': 3,
                    'feedback_lines': {
                        '1': [{
                            'text': 'This is very bad!',
                            'of_tutor': 'tutor'
                        }],
                    }
                }
            }]
        })

        self.student = self.test_data['students'][0].student
        self.reviewer = self.test_data['reviewers'][0]
        self.tutor = self.test_data['tutors'][0]
        self.submission = self.test_data['submissions'][0]

        self.request = self.factory.get(reverse('student-list'))
        self.view = StudentReviewerApiViewSet.as_view({'get': 'list'})

        force_authenticate(self.request, user=self.reviewer)
        self.rev_response = self.view(self.request)

        force_authenticate(self.request, user=self.tutor)
        self.tut_response = self.view(self.request)

    def test_reviewer_can_access(self):
        self.assertEqual(self.rev_response.status_code, status.HTTP_200_OK)

    def test_tutor_can_see_no_students_when_not_in_exercise_mode(self):
        self.assertEqual(0, len(self.tut_response.data))

    def test_reviewer_can_see_all_students(self):
        self.assertEqual(3, len(self.rev_response.data))

    @override_config(EXERCISE_MODE=True)
    def test_tutor_can_only_see_group_members_when_in_exercise_mode(self):
        force_authenticate(self.request, user=self.tutor)
        response = self.view(self.request)
        self.assertEqual(2, len(response.data))

    def test_submissions_score_is_included(self):
        res_with_sub = None
        for res in self.rev_response.data:
            if len(res['submissions']) > 0:
                res_with_sub = res
        self.assertEqual(self.student.submissions.first().feedback.score,
                         res_with_sub['submissions'][0]['score'])

    def test_submissions_full_score_is_included(self):
        res_with_sub = None
        for res in self.rev_response.data:
            if len(res['submissions']) > 0:
                res_with_sub = res
        self.assertEqual(self.student.submissions.first().type.full_score,
                         res_with_sub['submissions'][0]['full_score'])

    def tutor_can_not_deactivate_students(self):
        self.client.force_authenticate(self.tutor)
        response = self.client.post(reverse('student-list') + 'deactivate/')
        self.assertEqual(status.HTTP_401_UNAUTHORIZED, response.status_code)
        users = [stud.user for stud in models.StudentInfo.objects.all()]
        self.assertTrue(all([user.is_active for user in users]))

    def tutor_can_not_activate_students(self):
        self.client.force_authenticate(self.tutor)
        response = self.client.post(reverse('student-list') + 'activate/')
        self.assertEqual(status.HTTP_401_UNAUTHORIZED, response.status_code)

    def test_can_deactivate_all_students(self):
        self.client.force_authenticate(self.reviewer)
        self.client.post(reverse('student-list') + 'deactivate/')
        users = [stud.user for stud in models.StudentInfo.objects.all()]
        self.assertTrue(all([not user.is_active for user in users]))

    def test_can_activate_all_students(self):
        self.client.force_authenticate(self.reviewer)
        self.client.post(reverse('student-list') + 'activate/')
        users = [stud.user for stud in models.StudentInfo.objects.all()]
        self.assertTrue(all([user.is_active for user in users]))