from ..forms.quiz import StartQuiz
from ..models import Entry, Test
from ..tools.forms import send_errors_to_client
from ..tools.test import redirect_if_started

from flask import abort, Blueprint, jsonify, redirect, render_template, request, session
from flask.helpers import flash, url_for

from datetime import datetime

quiz = Blueprint(
    name='quiz',
    import_name=__name__,
    template_folder='templates',
    static_folder='static',
    static_url_path='/quiz/static'
)

@quiz.route('/')
@quiz.route('/home/')
@redirect_if_started
def _home():
    return render_template('/quiz/index.html')

@quiz.route('/instructions/')
def _instructions():
    return render_template('/quiz/instructions.html')

@quiz.route('/start/', methods=['GET', 'POST'])
def _start():
    form = StartQuiz()
    if request.method == 'POST':
        if form.validate_on_submit():
            entry = Entry()
            entry.set_first_name(request.form.get('first_name'))
            entry.set_surname(request.form.get('surname'))
            entry.set_club(request.form.get('club'))
            entry.set_email(request.form.get('email'))
            code = request.form.get('test_code').replace('—', '').lower()
            test = Test.query.filter_by(code=code).first()
            entry.test = test
            entry.user_code = request.form.get('user_code')
            entry.user_code = None if entry.user_code == '' else entry.user_code.lower()
            if not test:  return jsonify({'error': 'The exam code you entered is invalid.'}), 400
            if entry.user_code and entry.user_code not in test.adjustments: return jsonify({'error': f'The user code you entered is not valid.'}), 400
            if test.end_date < datetime.now(): return jsonify({'error': f'The exam code you entered expired on {test["expiry_date"].strftime("%d %b %Y %H:%M")}.'}), 400
            if test.start_date > datetime.now(): return jsonify({'error': f'The exam has not yet opened. Your exam code will be valid from {test["start_date"].strftime("%d %b %Y %H:%M")}.'}), 400
            success, message = entry.ready()
            if success:
                session['id'] = entry.id
                return jsonify({
                    'success': 'Received and validated test and/or user code. Redirecting to test client.',
                    'id': entry.id
                }), 200
            return jsonify({'error': 'There was an error processing the user test and/or user codes.'}), 400
        return send_errors_to_client(form=form)
    return render_template('/quiz/start_quiz.html', form = form)

@quiz.route('/quiz/')
def _quiz():
    id = session.get('id')
    if not id or not Entry.query.filter_by(id=id).first():
        flash('Your session was not recognised. Please sign in to the quiz again.', 'error')
        session.pop('id', None)
        return redirect(url_for('quiz._start'))
    return render_template('/quiz/client.html')

@quiz.route('/result/')
def _result():
    id = session.get('id')
    entry = Entry.query.filter_by(id=id).first()
    if not entry: return abort(404)
    session.pop('id',None)
    score = round(100*entry.result['score']/entry.result['max'])
    tags_low = { tag: tag_result['max'] - tag_result['scored'] for tag, tag_result in entry.result['tags'].items() }
    sorted_low_tags = sorted(tags_low.items(), key=lambda x: x[1], reverse=True)
    tag_output = [ tag[0] for tag in sorted_low_tags[0:3] if tag[1] > 3]
    if not entry.status == 'late':
        entry.notify_result()
    return render_template('/quiz/result.html', entry=entry, score=score, tag_output=tag_output)