from datetime import datetime, timedelta

from flask import current_app, flash, redirect, render_template, request, url_for
from flask_login import current_user, login_user, logout_user, login_required
from werkzeug.urls import url_parse

from app import db
from app.email import send_email, notify_admins
from app.user import bp
from app.user.forms import LoginForm, RegistrationForm, ProfileForm, \
  RequestPasswordResetForm, PasswordResetForm
from app.user.decorators import check_confirmed, check_sshkey
from app.user.token import generate_token, confirm_token
from app.models import User, UserRole, UserOrganization

@bp.route('/login', methods=['GET', 'POST'])
def login():
  if current_user.is_authenticated:
    return redirect(url_for('main.index'))
  form = LoginForm()
  if form.validate_on_submit():
    user = User.query.filter_by(email=form.email.data).first()
    if user is None or not user.check_password(form.password.data):
      flash('Invalid email or password', 'danger')
      return redirect(url_for('user.login'))
    login_user(user, remember=form.remember_me.data)
    next_page = request.args.get('next')
    if not next_page or url_parse(next_page).netloc != '':
      next_page = url_for('main.index')
    return redirect(next_page)
  return render_template('user/login.html', title='[nolabs] | Login', form=form)

@bp.route('/logout')
def logout():
  logout_user()
  return redirect(url_for('main.index'))

@bp.route('/register', methods=['GET', 'POST'])
def register():
  if current_user.is_authenticated:
    return redirect(url_for('main.index'))
  form = RegistrationForm()
  if form.validate_on_submit():
    role_id = UserRole.query.filter_by(role_name='regular').first().id
    org_id = UserOrganization.query.filter_by(org_name='nordix').first().id
    user = User(username=form.email.data, email=form.email.data, role_id=role_id, org_id=org_id)
    user.set_password(form.password.data)
    db.session.add(user)
    db.session.commit()
    token = generate_token(form.email.data)
    flash('Congratulations, you are now a registered user!', 'success')
    confirm_url = url_for('user.confirm', token=token, _external=True)
    email_body_html = render_template('user/activation_mail.html', confirm_url=confirm_url)
    send_email('Please confirm your Nordix Open Labs email', form.email.data, email_body_html)
    notify_admins('[nolabs] User Registered', form.email.data)
    flash('A confirmation email has been sent to your email adddress. Please check your spam mail folder as well.', 'success')
    flash('Please confirm your mail address within 24 hours.', 'warning')
    return redirect(url_for('user.login'))
  return render_template('user/register.html', title='[nolabs] | Register', form=form)

@bp.route('/request_password_reset', methods=['GET', 'POST'])
def request_password_reset():
  if current_user.is_authenticated:
    return redirect(url_for('main.index'))
  form = RequestPasswordResetForm()
  if form.validate_on_submit():
    user = User.query.filter_by(email=form.email.data).first()
    if user is None:
      flash('There is no user with the provided email address!', 'danger')
      return redirect(url_for('user.request_password_reset'))
    token = generate_token(form.email.data)
    password_reset_url = url_for('user.password_reset', token=token, _external=True)
    email_body_html = render_template('user/password_reset_mail.html', password_reset_url=password_reset_url)
    send_email('Reset your Nordix Open Labs password', form.email.data, email_body_html)
    flash('An email with instructions has been sent to your email address.', 'success')
    next_page = request.args.get('next')
    if not next_page or url_parse(next_page).netloc != '':
      next_page = url_for('user.login')
    return redirect(next_page)
  return render_template('user/request_password_reset.html', title='[nolabs] | Password Reset', form=form)

@bp.route('/password_reset/<token>', methods=['GET', 'POST'])
def password_reset(token):
  if current_user.is_authenticated:
    return redirect(url_for('main.index'))
  email = confirm_token(token)
  user = User.query.filter_by(email=email).first()
  if user is None or user.email != email:
    flash('The password reset link is either invalid or has expired.', 'danger')
    return redirect(url_for('user.request_password_reset'))
  form = PasswordResetForm()
  if form.validate_on_submit():
    if form.email.data != email:
      flash('Invalid email!', 'danger')
      return redirect(url_for('user.login'))
    user.set_password(form.password.data)
    db.session.commit()
    flash('Your password is now changed. Please use your new password when you login next time.', 'success')
    email_body_html = render_template('user/notify_password_reset.html', request_password_reset=request_password_reset)
    send_email('Your Nordix Open Labs password is reset', form.email.data, email_body_html)
    return redirect(url_for('user.login'))
  return render_template('user/password_reset.html', title='[nolabs] | Password Reset', form=form)

@bp.route('/confirm/<token>', methods=['GET', 'POST'])
@login_required
def confirm(token):
  if current_user.confirmed:
    flash('Account already confirmed!', 'success')
    return render_template('index.html', title='[nolabs] | Nordix Open Labs', text=current_app.news_content)

  email = confirm_token(token)
  user = User.query.filter_by(email=email).first()
  if user.email == email:
    user.confirmed = 1
    user.confirmed_on = datetime.utcnow().isoformat()
    db.session.commit()
    flash('You have confirmed your account now. Enjoy!', 'success')
    notify_admins('[nolabs] User Confirmed', user.email)
  else:
    flash('The confirmation link is either invalid or has expired.', 'danger')
  return render_template('index.html', title='[nolabs] | Nordix Open Labs', text=current_app.news_content)

@bp.route('/unconfirmed', methods=['GET'])
@login_required
def unconfirmed():
  if current_user.confirmed:
    next_page = request.args.get('next')
    if not next_page or url_parse(next_page).netloc != '':
      next_page = url_for('main.index')
    return redirect(next_page)
  flash('Your mail address is not confirmed yet. Please confirm it to access full functionality!', 'danger')
  return render_template('user/unconfirmed.html')

@bp.route('/profile', methods=['GET', 'POST'])
@login_required
@check_confirmed
def profile():
  form = ProfileForm(current_user.email)
  if not current_user.confirmed:
    flash('Your mail address is not confirmed yet. Please confirm it to access full functionality.', 'danger')
  if current_user.ssh_public_key is None or not current_user.ssh_public_key:
    flash("You either haven't registered your SSH Public Key or it is invalid. Please register your SSH Public Key in order to be able to make a new booking!", 'danger')
  if form.validate_on_submit():
    current_user.fullname = form.fullname.data
    current_user.ssh_public_key = form.ssh_public_key.data
    db.session.commit()
    db.session.flush()
    flash('Your changes have been saved.', 'success')
    return redirect(url_for('user.profile'))
  elif request.method == 'GET':
    form.email.data = current_user.email
    form.fullname.data = current_user.fullname
    form.organization.data = UserOrganization.query.filter_by(id=current_user.org_id).first().org_name
    form.role.data = UserRole.query.filter_by(id=current_user.role_id).first().role_name
    form.email.data = current_user.email
    form.ssh_public_key.data = current_user.ssh_public_key
    form.registered_on.data = current_user.registered_on
    form.confirmed_on.data = current_user.confirmed_on
    form.last_logged_in.data = current_user.last_logged_in
  return render_template('user/profile.html', title = '[nolabs] | Profile', form=form)
