from django.test import TestCase

from vbv_lernwelt.core.constants import TEST_STUDENT1_USER_ID
from vbv_lernwelt.core.create_default_users import create_default_users
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.creators.test_course import (
    create_test_course,
    create_test_uk_circle_fahrzeug,
)
from vbv_lernwelt.course.models import (
    CourseCompletion,
    CourseSession,
    CourseSessionUser,
)
from vbv_lernwelt.course.services import mark_course_completion
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
from vbv_lernwelt.course_session.services.attendance import (
    AttendanceUserStatus,
    update_attendance_list,
)
from vbv_lernwelt.learnpath.models import Circle, LearningPath
from vbv_lernwelt.notify.email.reminders.attendance import get_recipients


class AttendanceServicesTestCase(TestCase):
    def setUp(self):
        create_default_users()
        create_test_course(include_vv=False, with_sessions=True)
        self.course_session = CourseSession.objects.get(title="Test Bern 2022 a")
        self.attendance_course = (
            self.course_session.coursesessionattendancecourse_set.first()
        )
        self.trainer = User.objects.get(username="test-trainer1@example.com")
        self.client.force_login(self.trainer)

    def test_updateAttendanceList_withSingleUserId_findsDetailsAndStoresResult(self):
        student = User.objects.get(username="test-student1@example.com")

        update_attendance_list(
            self.attendance_course,
            [{"user_id": student.id, "status": AttendanceUserStatus.PRESENT}],
        )

        attendance_course = CourseSessionAttendanceCourse.objects.get(
            id=self.attendance_course.id
        )
        self.assertEqual(
            attendance_course.attendance_user_list[0]["user_id"], str(student.id)
        )
        self.assertEqual(
            attendance_course.attendance_user_list,
            [
                {
                    "email": "test-student1@example.com",
                    "status": "PRESENT",
                    "user_id": TEST_STUDENT1_USER_ID,
                    "last_name": "Student1",
                    "first_name": "Test",
                }
            ],
        )

    def test_updateAttendanceList_willUpdateUserCourseCompletion(self):
        student = User.objects.get(username="test-student1@example.com")
        update_attendance_list(
            self.attendance_course,
            [{"user_id": student.id, "status": AttendanceUserStatus.PRESENT}],
        )
        self.assertEqual(CourseCompletion.objects.count(), 1)
        cc = CourseCompletion.objects.first()
        self.assertEqual(cc.user, student)
        self.assertEqual(cc.completion_status, "SUCCESS")
        self.assertEqual(cc.page_id, self.attendance_course.learning_content.id)

    def test_updateAttendanceList_withRemovedUser_willUpdateUserCourseCompletion(self):
        student = User.objects.get(username="test-student1@example.com")
        self.attendance_course.attendance_user_list = [
            {
                "email": "test-student1@example.com",
                "status": "PRESENT",
                "user_id": TEST_STUDENT1_USER_ID,
                "last_name": "Student1",
                "first_name": "Test",
            }
        ]
        self.attendance_course.save()
        mark_course_completion(
            page=self.attendance_course.learning_content,
            user=student,
            course_session=self.course_session,
            completion_status="SUCCESS",
        )
        update_attendance_list(self.attendance_course, [])

        self.assertEqual(CourseCompletion.objects.count(), 1)
        cc = CourseCompletion.objects.first()
        self.assertEqual(cc.user, student)
        self.assertEqual(cc.completion_status, "FAIL")
        self.assertEqual(cc.page_id, self.attendance_course.learning_content.id)


class AttendanceReminderTestCase(TestCase):
    def setUp(self):
        create_default_users()
        create_test_course(include_vv=False, with_sessions=True)
        self.course_session = CourseSession.objects.get(title="Test Bern 2022 a")
        self.attendance_course = (
            self.course_session.coursesessionattendancecourse_set.first()
        )
        self.trainer = User.objects.get(username="test-trainer1@example.com")
        self.other_circle_title = "Something different"
        lp = LearningPath.objects.get(title="Test Lernpfad")
        create_test_uk_circle_fahrzeug(lp, title=self.other_circle_title)
        csu = CourseSessionUser.objects.get(user=self.trainer)
        fahrzeug = Circle.objects.get(title="Fahrzeug")
        csu.expert.add(fahrzeug)

    def test_reminderOnlySendsToMembersAndRelevantExperts(self):
        # promote user to expert, but in another circle
        csu = CourseSessionUser.objects.get(user__email="test-student3@example.com")
        other_circle = Circle.objects.get(title=self.other_circle_title)
        csu.role = CourseSessionUser.Role.EXPERT
        csu.save()
        csu.expert.add(other_circle)

        expected_csu = {
            "test-student1@example.com",
            "test-student2@example.com",
            "test-trainer1@example.com",
        }
        csus = get_recipients(self.attendance_course)
        self.assertEqual(set([u.user.email for u in csus]), expected_csu)
