"""
Public growth funnels (Part 8 ASAP): free diagnostic quiz.
"""
from __future__ import annotations

from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect, render
from django.views import View

from apps.courses.exam_generation import InsufficientQuestionBank
from apps.courses.forms import DiagnosticLeadForm
from apps.courses.growth_service import save_diagnostic_attempt, select_diagnostic_questions
from apps.courses.models import Course, CourseQuestion, DiagnosticAttempt


SESSION_Q_KEY = 'diagnostic_qids_{course_id}'
SESSION_ANS_KEY = 'diagnostic_answers_{course_id}'


def _get_diagnostic_course(slug):
    """Published course with free skill check enabled."""
    return get_object_or_404(
        Course.objects.filter(
            status='published',
            is_active=True,
            enable_free_diagnostic=True,
        ),
        slug=slug,
    )


class DiagnosticIntroView(View):
    """Public landing — no login."""
    template_name = 'courses/diagnostic_intro.html'

    def get(self, request, slug):
        course = _get_diagnostic_course(slug)
        return render(request, self.template_name, {'course': course})


class DiagnosticQuizView(View):
    template_name = 'courses/diagnostic_quiz.html'

    def get_course(self, slug):
        return _get_diagnostic_course(slug)

    def _session_keys(self, course_id):
        return (
            SESSION_Q_KEY.format(course_id=course_id),
            SESSION_ANS_KEY.format(course_id=course_id),
        )

    def get(self, request, slug):
        course = self.get_course(slug)
        q_key, _ = self._session_keys(course.pk)
        qids = request.session.get(q_key)
        if not qids:
            try:
                questions = select_diagnostic_questions(course)
            except InsufficientQuestionBank as exc:
                messages.error(request, str(exc))
                return redirect('courses:course_detail', slug=slug)
            qids = [q.pk for q in questions]
            request.session[q_key] = qids
        else:
            questions = list(
                CourseQuestion.objects.filter(pk__in=qids, course=course)
            )
            order = {pk: i for i, pk in enumerate(qids)}
            questions.sort(key=lambda q: order.get(q.pk, 0))

        return render(request, self.template_name, {
            'course': course,
            'questions': questions,
        })

    def post(self, request, slug):
        """Save answers in session → redirect to lead capture (gate before score)."""
        course = self.get_course(slug)
        q_key, a_key = self._session_keys(course.pk)
        qids = request.session.get(q_key) or []
        if not qids:
            messages.warning(request, 'Start the diagnostic again.')
            return redirect('courses:diagnostic_intro', slug=slug)

        answers = {}
        for qid in qids:
            val = (request.POST.get(f'q_{qid}') or '').strip().upper()
            if val in ('A', 'B', 'C', 'D'):
                answers[qid] = val
        request.session[a_key] = answers
        return redirect('courses:diagnostic_lead', slug=slug)


class DiagnosticLeadView(View):
    """Capture email/WhatsApp, then persist score and show result."""
    template_name = 'courses/diagnostic_lead.html'

    def get_course(self, slug):
        return _get_diagnostic_course(slug)

    def get(self, request, slug):
        course = self.get_course(slug)
        q_key = SESSION_Q_KEY.format(course_id=course.pk)
        a_key = SESSION_ANS_KEY.format(course_id=course.pk)
        if not request.session.get(q_key) or request.session.get(a_key) is None:
            return redirect('courses:diagnostic_quiz', slug=slug)
        return render(request, self.template_name, {
            'course': course,
            'form': DiagnosticLeadForm(),
        })

    def post(self, request, slug):
        course = self.get_course(slug)
        form = DiagnosticLeadForm(request.POST)
        q_key = SESSION_Q_KEY.format(course_id=course.pk)
        a_key = SESSION_ANS_KEY.format(course_id=course.pk)
        qids = request.session.get(q_key) or []
        answers = request.session.get(a_key)
        if answers is None or not qids:
            return redirect('courses:diagnostic_quiz', slug=slug)

        if not form.is_valid():
            return render(request, self.template_name, {'course': course, 'form': form})

        questions = list(CourseQuestion.objects.filter(pk__in=qids, course=course))
        order = {pk: i for i, pk in enumerate(qids)}
        questions.sort(key=lambda q: order.get(q.pk, 0))

        attempt = save_diagnostic_attempt(
            course=course,
            email=form.cleaned_data['email'],
            whatsapp=form.cleaned_data.get('whatsapp') or '',
            answers=answers,
            questions=questions,
        )
        # Clear quiz session
        request.session.pop(q_key, None)
        request.session.pop(a_key, None)
        return redirect('courses:diagnostic_result', pk=attempt.pk)


class DiagnosticResultView(View):
    template_name = 'courses/diagnostic_result.html'

    def get(self, request, pk):
        attempt = get_object_or_404(
            DiagnosticAttempt.objects.select_related('course'),
            pk=pk,
        )
        return render(request, self.template_name, {
            'attempt': attempt,
            'course': attempt.course,
        })
