from flask import Blueprint, render_template, request, session, redirect
from flask.helpers import flash, url_for
from flask.json import jsonify
from .models.users import User
from uuid import uuid4
from common.security.database import decrypt_find_one, encrypted_update
from werkzeug.security import check_password_hash

from main import db

from .views import admin_account_required, disable_on_registration, login_required, disable_if_logged_in, get_id_from_cookie

auth = Blueprint(
    'admin_auth',
    __name__,
    template_folder='templates',
    static_folder='static'
)

@auth.route('/account/', methods = ['GET', 'POST'])
@admin_account_required
@login_required
def account():
    from .models.forms import UpdateAccountForm
    form = UpdateAccountForm()
    _id = get_id_from_cookie()
    user = decrypt_find_one(db.users, {'_id': _id})
    if request.method == 'GET':
        return render_template('/admin/auth/account.html', form = form, user = user)
    if request.method == 'POST':
        if form.validate_on_submit():
            password_confirm = request.form.get('password_confirm')
            if not check_password_hash(user['password'], password_confirm):
                return jsonify({ 'error': 'The password you entered is incorrect.' }), 401
            entry = User(
                _id = _id,
                password = request.form.get('password'),
                email = request.form.get('email')
            )
            return entry.update()
        else:
            errors = [*form.password_confirm.errors, *form.password_reenter.errors, *form.password.errors, *form.email.errors]
            return jsonify({ 'error': errors}), 400

@auth.route('/login/', methods=['GET','POST'])
@admin_account_required
@disable_if_logged_in
def login():
    from .models.forms import LoginForm
    form = LoginForm()
    if request.method == 'GET':
        return render_template('/admin/auth/login.html', form=form)
    if request.method == 'POST':
        if form.validate_on_submit():
            entry = User(
                username = request.form.get('username').lower(),
                password = request.form.get('password'),
                remember = request.form.get('remember')
            )
            return entry.login()
        else:
            errors = [*form.username.errors, *form.password.errors]
            return jsonify({ 'error': errors}), 400

@auth.route('/logout/')
@admin_account_required
@login_required
def logout():
    _id = get_id_from_cookie()
    return User(_id=_id).logout()

@auth.route('/register/', methods=['GET','POST'])
@disable_on_registration
def register():
    from .models.forms import RegistrationForm
    form = RegistrationForm()
    if request.method == 'GET':
        return render_template('/admin/auth/register.html', form=form)
    if request.method == 'POST':
        if form.validate_on_submit():
            entry = User(
                _id = uuid4().hex,
                username = request.form.get('username').lower(),
                email = request.form.get('email'),
                password = request.form.get('password'),
            )
            return entry.register()
        else:
            errors = [*form.username.errors, *form.email.errors, *form.password.errors, *form.password_reenter.errors]
            return jsonify({ 'error': errors}), 400

@auth.route('/reset/', methods = ['GET', 'POST'])
@admin_account_required
@disable_if_logged_in
def reset():
    from .models.forms import ResetPasswordForm
    form = ResetPasswordForm()
    if request.method == 'GET':
        return render_template('/admin/auth/reset.html', form=form)
    if request.method == 'POST':
        if form.validate_on_submit():
            entry = User(
                username = request.form.get('username').lower(),
                email = request.form.get('email'),
            )
            return entry.reset_password()
        else:
            errors = [*form.username.errors, *form.email.errors]
            return jsonify({ 'error': errors}), 400

@auth.route('/reset/<token1>/<token2>/', methods = ['GET'])
@admin_account_required
@disable_if_logged_in
def reset_gateway(token1,token2):
    from main import db
    user = decrypt_find_one( db.users, {'reset_token' : token1} )
    if not user:
        return redirect(url_for('admin_auth.login'))
    encrypted_update( db.users, {'reset_token': token1}, {'$unset': {'reset_token' : '', 'verification_token': ''}})
    if not user['verification_token'] == token2:
        flash('The verification of your password reset request failed and the token has been invalidated. Please make a new reset password request.', 'error'), 401
        return redirect(url_for('admin_auth.reset'))
    session['_id'] = user['_id']
    session['reset_validated'] = True
    return redirect(url_for('admin_auth.update_password_'))

@auth.route('/reset/update/', methods = ['GET','POST'])
@admin_account_required
@disable_if_logged_in
def update_password_():
    from .models.forms import UpdatePasswordForm
    form = UpdatePasswordForm()
    if request.method == 'GET':
        if 'reset_validated' not in session:
            return redirect(url_for('admin_auth.login'))
        session.pop('reset_validated')
        return render_template('/admin/auth/update-password.html', form=form)
    if request.method == 'POST':
        if form.validate_on_submit():
            entry = User(
                _id = session['_id'],
                password = request.form.get('password')
            )
            session.pop('_id')
            return entry.update()
        else:
            errors = [*form.password.errors, *form.password_reenter.errors]
            return jsonify({ 'error': errors}), 400