from datetime import date
import random

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required
from django.db.models import Avg, Sum
from django.utils import timezone

from accounts.models import User
from question_bank.models import QuestionBank

from .forms import GenerateDailyQuizForm
from .models import (
    StudentProfile,
    DailyQuiz,
    DailyQuizQuestion,
    StudentDailyQuizAttempt,
    StudentDailyQuizAnswer
)


# =========================================
# Student Check
# =========================================

def is_student(user):
    return user.is_authenticated and user.user_type == "student"


# =========================================
# Student Dashboard
# =========================================

@login_required
def students_dashboard(request):

    if not is_student(request.user):
        return redirect("login")

    attempts = StudentDailyQuizAttempt.objects.filter(
        student=request.user
    ).order_by("-submitted_at")

    total_attempts = attempts.count()
    total_score = attempts.aggregate(total=Sum("score"))["total"] or 0
    average_score = attempts.aggregate(avg=Avg("score"))["avg"] or 0

    context = {
        "total_attempts": total_attempts,
        "total_score": total_score,
        "average_score": round(average_score, 2),
        "attempts": attempts[:10],
    }

    return render(request, "students/dashboard.html", context)


# =========================================
# Daily Quiz Page
# =========================================

@login_required
def daily_quiz(request):

    if not is_student(request.user):
        return redirect("login")

    today = date.today()

    quiz = DailyQuiz.objects.filter(date=today).first()

    if not quiz:
        return render(request, "students/no_quiz.html")

    if StudentDailyQuizAttempt.objects.filter(
        student=request.user,
        quiz=quiz
    ).exists():
        return render(request, "students/already_attempted.html")

    questions = DailyQuizQuestion.objects.filter(
        quiz=quiz
    ).select_related("question").order_by("order")

    grouped_questions = {}

    for item in questions:
        q = item.question
        base_id = q.base_question_id

        if base_id not in grouped_questions:
            grouped_questions[base_id] = {
                "english": None,
                "hindi": None
            }

        if q.language == "e":
            grouped_questions[base_id]["english"] = q

        if q.language == "h":
            grouped_questions[base_id]["hindi"] = q

    return render(request, "students/daily_quiz.html", {
        "quiz": quiz,
        "grouped_questions": grouped_questions.values(),
        "show_result": False,
        "selected_answers": {}
    })


# =========================================
# Submit Quiz
# =========================================

@login_required
def submit_daily_quiz(request):

    if request.method != "POST":
        return redirect("students_dashboard")

    quiz_id = request.POST.get("quiz_id")
    quiz = get_object_or_404(DailyQuiz, id=quiz_id)

    if StudentDailyQuizAttempt.objects.filter(
        student=request.user,
        quiz=quiz
    ).exists():
        return redirect("daily_quiz")

    attempt = StudentDailyQuizAttempt.objects.create(
        student=request.user,
        quiz=quiz
    )

    questions = DailyQuizQuestion.objects.filter(
        quiz=quiz
    ).select_related("question").order_by("order")

    # -----------------------------------------
    # Group English + Hindi by base_question_id
    # -----------------------------------------

    grouped_questions = {}

    for item in questions:

        q = item.question
        base_id = q.base_question_id

        if base_id not in grouped_questions:
            grouped_questions[base_id] = {
                "english": None,
                "hindi": None
            }

        if q.language == "e":
            grouped_questions[base_id]["english"] = q

        if q.language == "h":
            grouped_questions[base_id]["hindi"] = q

    # -----------------------------------------
    # Score Calculation
    # -----------------------------------------

    total_score = 0
    total_negative = 0
    total_marks = 0

    correct_count = 0
    wrong_count = 0

    selected_answers = {}

    for base_id, pair in grouped_questions.items():

        q = pair["english"]   # use English record for checking

        if not q:
            continue

        # ✅ IMPORTANT FIX
        selected = request.POST.get(f"question_{base_id}")

        selected_answers[base_id] = selected

        StudentDailyQuizAnswer.objects.create(
            attempt=attempt,
            question=q,
            selected_option=selected
        )

        total_marks += q.marks

        if selected:

            # normalize comparison
            selected = selected.strip().upper()
            correct = (q.correct_answer_choice or "").strip().upper()

            if selected == correct:

                total_score += q.marks
                correct_count += 1

            else:

                total_negative += q.negative_marks
                wrong_count += 1

    # -----------------------------------------
    # Final Score
    # -----------------------------------------

    final_score = total_score - total_negative

    total_questions = len(grouped_questions)

    accuracy = 0
    if total_questions > 0:
        accuracy = (correct_count / total_questions) * 100

    attempt.score = final_score
    attempt.save()

    return render(request, "students/daily_quiz.html", {
        "quiz": quiz,
        "grouped_questions": grouped_questions.values(),
        "show_result": True,
        "score": round(final_score, 2),
        "total_marks": total_marks,
        "correct_count": correct_count,
        "wrong_count": wrong_count,
        "accuracy": round(accuracy, 2),
        "selected_answers": selected_answers
    })

# =========================================
# Random + Manual Daily Quiz Generator (Admin)
# =========================================

@staff_member_required
def generate_daily_quiz(request):

    # =========================================
    # CREATE ENGLISH + HINDI PAIRS
    # (like generate_test view)
    # =========================================

    english_questions = QuestionBank.objects.filter(
        language='e',
        ai_version=0
    ).order_by("-id")

    questions = []

    for q_en in english_questions:

        q_hi = QuestionBank.objects.filter(
            base_question_id=q_en.base_question_id,
            language='h',
            ai_version=q_en.ai_version
        ).first()

        questions.append({
            "english": q_en,
            "hindi": q_hi
        })

    # =========================================
    # FORM SUBMIT
    # =========================================

    if request.method == "POST":

        form = GenerateDailyQuizForm(request.POST)

        if form.is_valid():

            mode = form.cleaned_data.get("mode")
            num_questions = form.cleaned_data["number_of_questions"]

            today = timezone.now().date()

            if DailyQuiz.objects.filter(date=today).exists():
                return render(request, "students/generate_quiz.html", {
                    "form": form,
                    "questions": questions,
                    "error": "Quiz already generated for today!"
                })

            quiz = DailyQuiz.objects.create(
                date=today,
                total_questions=num_questions
            )

            # =========================================
            # RANDOM MODE
            # =========================================

            if mode == "random":

                base_ids = QuestionBank.objects.filter(
                    language='e',
                    ai_version=0
                ).values_list(
                    "base_question_id", flat=True
                ).distinct()

                base_ids = list(base_ids)

                if num_questions > len(base_ids):

                    return render(request, "students/generate_quiz.html", {
                        "form": form,
                        "questions": questions,
                        "error": "Not enough questions available."
                    })

                selected_base_ids = random.sample(base_ids, num_questions)

                order = 1

                for base_id in selected_base_ids:

                    qs = QuestionBank.objects.filter(
                        base_question_id=base_id,
                        ai_version=0
                    )

                    for q in qs:

                        DailyQuizQuestion.objects.create(
                            quiz=quiz,
                            question=q,
                            order=order
                        )

                    order += 1

            # =========================================
            # MANUAL MODE (PAIR SAFE)
            # =========================================

            else:

                selected_ids = request.POST.getlist("selected_questions")

                if not selected_ids:

                    return render(request, "students/generate_quiz.html", {
                        "form": form,
                        "questions": questions,
                        "error": "Please select questions."
                    })

                if len(selected_ids) != num_questions:

                    return render(request, "students/generate_quiz.html", {
                        "form": form,
                        "questions": questions,
                        "error": f"You must select exactly {num_questions} questions."
                    })

                order = 1

                selected_en_questions = QuestionBank.objects.filter(
                    id__in=selected_ids,
                    language='e'
                )

                for q_en in selected_en_questions:

                    # Save English
                    DailyQuizQuestion.objects.create(
                        quiz=quiz,
                        question=q_en,
                        order=order
                    )

                    # Find Hindi pair
                    q_hi = QuestionBank.objects.filter(
                        base_question_id=q_en.base_question_id,
                        language='h',
                        ai_version=q_en.ai_version
                    ).first()

                    if q_hi:

                        DailyQuizQuestion.objects.create(
                            quiz=quiz,
                            question=q_hi,
                            order=order
                        )

                    order += 1

            return redirect("admin_dashboard")

    else:
        form = GenerateDailyQuizForm()

    return render(request, "students/generate_quiz.html", {
        "form": form,
        "questions": questions
    })

# =========================================
# Daily Leaderboard
# =========================================

@login_required
def daily_leaderboard(request):

    today = date.today()

    quiz = DailyQuiz.objects.filter(date=today).first()

    if not quiz:
        return render(request, "students/no_quiz.html")

    attempts = StudentDailyQuizAttempt.objects.filter(
        quiz=quiz
    ).select_related("student").order_by("-score", "submitted_at")

    ranked_attempts = []
    rank = 1

    for attempt in attempts:

        ranked_attempts.append({
            "rank": rank,
            "student": attempt.student,
            "score": attempt.score,
            "submitted_at": attempt.submitted_at
        })

        rank += 1

    return render(request, "students/daily_leaderboard.html", {
        "quiz": quiz,
        "ranked_attempts": ranked_attempts
    })