# retoor <retoor@molodetz.nl>

from __future__ import annotations

from .common import QuizError, get_quiz
from .questions import add_question, list_questions, options_by_question
from .quizzes import recompute_quiz_totals

OPTION_KINDS = {"single_choice", "multiple_choice", "fill_blank", "ordering", "matching"}


def parse_document(payload):
    from devplacepy.models import QuizDocument

    try:
        return QuizDocument.model_validate(payload)
    except Exception as exc:
        raise QuizError(f"Invalid quiz document: {exc}") from exc


def document_settings(document) -> dict:
    settings = document.settings
    return {
        "shuffle_questions": int(bool(settings.shuffle_questions)),
        "shuffle_options": int(bool(settings.shuffle_options)),
        "reveal_answers": int(bool(settings.reveal_answers)),
        "allow_review": int(bool(settings.allow_review)),
        "time_limit_seconds": max(0, int(settings.time_limit_seconds or 0)),
        "pass_percent": max(0, min(100, int(settings.pass_percent or 0))),
    }


def import_questions(quiz_uid: str, document) -> int:
    for question in document.questions:
        add_question(
            quiz_uid,
            {
                "kind": question.kind,
                "prompt": question.prompt,
                "explanation": question.explanation,
                "points": question.points,
                "media_attachment_uid": question.media_attachment_uid,
                "correct_boolean": int(bool(question.correct_boolean)),
                "expected_answer": question.expected_answer,
                "grading_criteria": question.grading_criteria,
                "numeric_value": question.numeric_value,
                "numeric_tolerance": question.numeric_tolerance,
                "case_sensitive": int(bool(question.case_sensitive)),
                "options": [
                    {
                        "label": option.label,
                        "match_value": option.match_value,
                        "is_correct": option.is_correct,
                    }
                    for option in question.options
                ],
            },
        )
    recompute_quiz_totals(quiz_uid)
    return len(document.questions)


def export_document(quiz_uid: str, include_answers: bool) -> dict:
    quiz = get_quiz(quiz_uid)
    if not quiz:
        raise QuizError("Quiz not found")
    grouped = options_by_question(quiz_uid)
    questions = []
    for question in list_questions(quiz_uid):
        payload = {
            "kind": question.get("kind") or "",
            "prompt": question.get("prompt") or "",
            "explanation": question.get("explanation") or "",
            "points": max(1, int(question.get("points") or 1)),
            "options": [
                _export_option(option, question.get("kind") or "", include_answers)
                for option in grouped.get(question["uid"], [])
            ],
        }
        if include_answers:
            payload["correct_boolean"] = bool(int(question.get("correct_boolean") or 0))
            payload["expected_answer"] = question.get("expected_answer") or ""
            payload["grading_criteria"] = question.get("grading_criteria") or ""
            payload["numeric_value"] = float(question.get("numeric_value") or 0.0)
            payload["numeric_tolerance"] = float(question.get("numeric_tolerance") or 0.0)
            payload["case_sensitive"] = bool(int(question.get("case_sensitive") or 0))
        questions.append(payload)
    return {
        "title": quiz.get("title") or "",
        "description": quiz.get("description") or "",
        "settings": {
            "shuffle_questions": bool(int(quiz.get("shuffle_questions") or 0)),
            "shuffle_options": bool(int(quiz.get("shuffle_options") or 0)),
            "reveal_answers": bool(int(quiz.get("reveal_answers") or 0)),
            "allow_review": bool(int(quiz.get("allow_review") or 0)),
            "time_limit_seconds": int(quiz.get("time_limit_seconds") or 0),
            "pass_percent": int(quiz.get("pass_percent") or 0),
        },
        "questions": questions,
    }


def _export_option(option: dict, kind: str, include_answers: bool) -> dict:
    payload = {"label": option.get("label") or ""}
    if include_answers:
        payload["is_correct"] = bool(int(option.get("is_correct") or 0))
        payload["match_value"] = option.get("match_value") or ""
    elif kind == "ordering":
        payload["match_value"] = ""
    return payload
