# Generated by Django 4.0.6 on 2022-09-03 14:33
from datetime import datetime

from django.db import migrations


def find_last_quizee_input_index(exam_page):
    index = 0
    groups = sorted(exam_page.generated_exam["groups"],
                    key=lambda item: item["index"] if "index" in item else 0)
    for g_index, group in enumerate(groups):
        questions = sorted(group["questions"],
                           key=lambda item: item["index"] if "index" in item else 0)
        for q_index, _ in enumerate(questions):
            if exam_page.first_available_group_index == g_index and exam_page.first_available_question_index == q_index:
                return max(0, index - 1)
            else:
                index += 1


def sheet_segment_creator(apps, schema_editor, generated_exam, user_inputs):
    Question = apps.get_model("question", "Question")

    db_alias = schema_editor.connection.alias

    questions_sheet = {'questions': [], 'groups': []}
    solutions_sheet = {'solutions': []}
    quizee_inputs_sheet = []

    absolute_index = 0

    groups = sorted(generated_exam["groups"],
                    key=lambda item: item["index"] if "index" in item else 0)

    question_number = 0

    for g_index, group in enumerate(groups):
        questions_sheet['groups'].append({'name': '', 'start_at': question_number})
        question_number += 1

        questions = sorted(group["questions"],
                           key=lambda item: item["index"] if "index" in item else 0)
        for q_index, question in enumerate(questions):

            question_obj = Question.objects.using(
                db_alias).get(id=question["question_id"])

            questions_sheet['questions'].append({
                "index": absolute_index,
                "format": question_obj.format,
                "choices": question_obj.choices,
                "input_rules": question_obj.input_rules,
                "question_text": question_obj.question_text,
                "question_type": question_obj.question_type,
                "duration": question["duration"],
                "positive_score": question["positive_score"],
                "negative_score": question["negative_score"],
            })

            solutions_sheet['solutions'].append(
                {"index": absolute_index,
                 "question_id": str(question_obj.id),
                 "solution": question_obj.solution,
                 "correct_choices": question_obj.correct_choices,
                 }
            )
            selected_user_input = None
            for user_input in user_inputs:
                if 'group_index' not in user_input or 'question_index' not in user_input:
                    break

                elif user_input['group_index'] == g_index and user_input['question_index'] == q_index:
                    selected_user_input = user_input
                    break
            if selected_user_input:
                selected_choices = [choice["id"] for choice in (question["answer_rules"]
                                                                .get("choices") or []) if
                                    choice["index"] in selected_user_input["answer_indexes"]]
                quizee_inputs_sheet.append({
                    "index": absolute_index,
                    "answer_time": selected_user_input["answer_time"],
                    "selected_choices": selected_choices,
                    "answer_text": selected_user_input.get("answer_text"),
                    "answer_text_format": selected_user_input.get("answer_text_format")
                })

            # last line
            absolute_index += 1

    return questions_sheet, solutions_sheet, quizee_inputs_sheet


class Migration(migrations.Migration):
    dependencies = [
        ('quiz', '0014_alter_quizsheet__quizee_inputs_sheet_and_more'),
    ]

    def modify(apps, schema_editor):

        Exam = apps.get_model("exam", "Exam")
        ExamPage = apps.get_model("exam", "ExamPage")
        Corrections = apps.get_model("exam", "Corrections")
        Quiz = apps.get_model("quiz", "Quiz")
        QuizSheet = apps.get_model("quiz", "QuizSheet")
        QuestionScore = apps.get_model("quiz", "QuestionScore")
        Question = apps.get_model("question", "Question")

        print("reading Exam data from database")

        db_alias = schema_editor.connection.alias
        exam_querysey = Exam.objects.using(db_alias).all()

        i = 0
        count = len(exam_querysey)
        previous_percent = -1

        for exam in exam_querysey:

            percent = 100 * i // count
            if previous_percent != percent:
                print(str(percent) + "%")
                previous_percent = percent
            i += 1

            name = exam.name

            institute = exam.institute

            single_question_at_a_time = exam.one_question_at_a_time
            reanswerable = exam.reanswer

            shuffle_questions = exam.shuffle_questions
            shuffle_choices = exam.shuffle_answers

            apply_negative_scores = exam.apply_negative_scores

            poster = exam.poster
            poster_thumbnail = exam.poster_thumbnail
            theme = exam.theme
            description = exam.description

            duration = exam.duration
            questions_count = exam.questions_count

            finish_message = exam.finish_message
            archived = exam.deleted

            created_at = exam.created_at
            modified_at = exam.modified_at
            price = exam.price or 0
            wage_free = False
            vax_free = False

            featured = False
            priority = 0

            start = exam.start_date
            end = exam.end_date

            rules = exam.rules
            groups = rules["groups"]

            new_groups = []

            retrievers = []

            question_number = 0

            for group in groups:
                new_groups.append({'name': group['name'], 'start_at': question_number})
                question_number += 1

                for question in group["questions"]:
                    referenced_question = Question.objects.using(
                        db_alias).get(pk=question["question_id"])
                    retrievers.append({
                        "insert_type": "REFERENCED_QUESTION",
                        "duration": question["duration"],
                        "negative_score": question["negative_score"],
                        "positive_score": question["positive_score"],
                        "question_bank_id": question.get("question_bank_id"),
                        "question_id": question["question_id"],
                        "count": 1,
                        "tag_filters": [],
                        "retrieved_at": str(datetime.now()),
                        "contents": [{
                            "id": str(referenced_question.id),
                            "keywords": referenced_question.keywords,
                            "question_text": referenced_question.question_text,
                            "format": referenced_question.format,
                            "choices": referenced_question.choices,
                            "correct_choices": referenced_question.correct_choices,
                            "input_rules": referenced_question.input_rules,
                            "solution": referenced_question.solution,
                            "question_type": referenced_question.question_type,
                            "tags": referenced_question.tags,
                        }]
                    })

            _blueprint = {"retrievers": retrievers, "groups": new_groups}
            quiz = Quiz.objects.using(db_alias).create(name=name, institute=institute, single_question_at_a_time=single_question_at_a_time,
                                                       reanswerable=reanswerable, shuffle_questions=shuffle_questions,
                                                       shuffle_choices=shuffle_choices, public=exam.public_id is not None,
                                                       apply_negative_scores=apply_negative_scores, poster=poster,
                                                       poster_thumbnail=poster_thumbnail, theme=theme, description=description,
                                                       duration=duration, questions_count=questions_count, finish_message=finish_message,
                                                       archived=archived, created_at=created_at, modified_at=modified_at, price=price,
                                                       wage_free=wage_free, vax_free=vax_free, featured=featured,
                                                       priority=priority, start=start, end=end, _blueprint=_blueprint)

            exam_page_queryset = ExamPage.objects.using(
                db_alias).filter(exam=exam)
            for exam_page in exam_page_queryset:
                sheet_segment_creator(apps=apps, schema_editor=schema_editor,
                                      generated_exam=exam_page.generated_exam, user_inputs=exam_page.user_inputs)

                _questions_sheet, _solutions_sheet, _quizee_inputs_sheet = sheet_segment_creator(
                    apps=apps, schema_editor=schema_editor, generated_exam=exam_page.generated_exam, user_inputs=exam_page.user_inputs)

                _quizee = exam_page.user

                _anonymous_quizee = exam_page.institute_student

                allowed_start_at = exam_page.start_date
                entrance_date = exam_page.entrance_date
                entrance_token = exam_page.entrance_token
                allowed_finish_at = exam_page.end_date
                duration = exam_page.duration
                report_card = exam_page.report_card

                created_at = exam_page.created_at
                modified_at = exam_page.modified_at

                final_score = exam_page.final_score
                state = exam_page.state

                stats = exam_page.report_card.get(
                    "overall") if exam_page.report_card else None

                last_quizee_input_index = find_last_quizee_input_index(
                    exam_page=exam_page)
                quiz_sheet = QuizSheet.objects.using(db_alias).create(quiz=quiz, final_score=final_score, state=state,
                                                                      _questions_sheet=_questions_sheet, _solutions_sheet=_solutions_sheet,
                                                                      _quizee_inputs_sheet=_quizee_inputs_sheet, duration=duration,
                                                                      _quizee=_quizee, _anonymous_quizee=_anonymous_quizee,
                                                                      allowed_start_at=allowed_start_at, entrance_date=entrance_date,
                                                                      entrance_token=entrance_token,
                                                                      allowed_finish_at=allowed_finish_at, created_at=created_at,
                                                                      modified_at=modified_at, report_card=report_card,
                                                                      last_quizee_input_index=last_quizee_input_index, stats=stats)

                corrections_queryset = Corrections.objects.using(db_alias).filter(exam_page=exam_page)
                for corrections in corrections_queryset:
                    QuestionScore.objects.using(db_alias).create(quiz_sheet=quiz_sheet, corrector=corrections.corrector,
                                                                 question=corrections.question, question_index=corrections.question_index,
                                                                 blank=corrections.blank, score=corrections.score,
                                                                 correct_choices=corrections.correct_choices,
                                                                 wrong_choices=corrections.wrong_choices,
                                                                 blank_choices=corrections.blank_choices,
                                                                 comment_for_student=corrections.comment_for_student,
                                                                 comment_for_other_correctors=corrections.comment_for_other_correctors,
                                                                 created_at=corrections.created_at, modified_at=corrections.modified_at)

    operations = [
        migrations.RunPython(modify),
    ]
