# Site Back-End Logic
from hmac import new
from flask import Blueprint, render_template, request, flash, redirect, url_for, make_response
from flask_login import login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
from .models import User, Message
from . import db
import string, secrets

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField, FileField, IntegerField, RadioField, TextAreaField
from wtforms.validators import DataRequired

logic = Blueprint('logic', __name__)

# WTForm Classes
class DescForm(FlaskForm):
    # declare form field, required input, placeholder and validate data
    description = TextAreaField(validators=[DataRequired()])
    submit = SubmitField('Update your Description')

class PasswdForm(FlaskForm):
    passwd_1 = PasswordField('Edit Password', validators=[DataRequired()])
    passwd_2 = PasswordField('Confirm Password', validators=[DataRequired()])
    submit = SubmitField('Update Password')

class MsgForm(FlaskForm):
    msg = TextAreaField(validators=[DataRequired()])
    submit = SubmitField('Send')

class LoginForm(FlaskForm):
    email = StringField(validators=[DataRequired()])
    passwd = PasswordField(validators=[DataRequired()])
    submit = SubmitField('Login')

class RegForm(FlaskForm):
    email = StringField(validators=[DataRequired()])
    passwd_1 = PasswordField(validators=[DataRequired()])
    passwd_2 = PasswordField(validators=[DataRequired()])
    firstname = StringField(validators=[DataRequired()])
    lastname = StringField(validators=[DataRequired()])
    age = IntegerField(validators=[DataRequired()])
    gender = RadioField('Gender', choices=[('M', 'Male'),('F', 'Female')], validators=[DataRequired()])
    submit = SubmitField('Register')



@logic.route('/', methods=['GET', 'POST'])
@login_required
def profile():

    form_1 = DescForm()
    form_2 = PasswdForm()

    # WTForm Validation Checks
    if form_1.validate_on_submit():
        new_desc = form_1.description.data
        form_1.description.data = ''
        new_desc_dbcall = User.query.filter_by(id=current_user.id).first()
        new_desc_dbcall.description = new_desc
        db.session.commit()
        flash('Hooray! A new description!', category='success')

    elif form_2.validate_on_submit():
        passwd_1 = form_2.passwd_1.data
        passwd_2 = form_2.passwd_2.data
        form_2.passwd_1.data = ''
        form_2.passwd_2.data = ''
        if passwd_1 == passwd_2:
            new_passwd_dbcall = User.query.filter_by(id=current_user.id).first()
            new_passwd_dbcall.password = generate_password_hash(passwd_2, method='sha256')
            db.session.commit()
            flash('Nice! Updated your password!', category='success')
        else:
            flash('Oh no! Your passwords must match!', category='error')

    # DB Insertions
    if request.method == "POST":
        new_pic = request.files.get('profilepic_upload')

        if new_pic:
            # generate random filename for uploaded file 
            alphanumeric = string.ascii_letters + string.digits
            ralphanum = ''.join(secrets.choice(alphanumeric) for i in range(16))
            new_pic_dbcall = User.query.filter_by(id=current_user.id).first()
            if '.png' in new_pic.filename:
                new_pic.save(f'app/static/uploads/{ralphanum}.png')
                new_pic_dbcall.profile_image = f'{ralphanum}.png'
            elif '.jpg' in new_pic.filename or 'jpeg' in new_pic.filename:
                new_pic.save(f'app/static/uploads/{ralphanum}.jpeg')
                new_pic_dbcall.profile_image = f'{ralphanum}.jpeg'
            db.session.commit()

    response = make_response(render_template("profile.html", user = current_user, form1 = form_1, form2= form_2))
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response


@logic.route('/matchbook', methods=['GET', 'POST'])
@login_required
def matchbook():
    all_users = User.query.all()

    if request.method == 'POST':
        recipient_id = request.form.get('message_recipient')
        fdbcall = User.query.filter_by(id=current_user.id).first()
        fdbcall.focus = recipient_id
        db.session.commit()
        response = make_response(redirect(url_for('logic.messaging')))
        response.headers['Content-Security-Policy'] = "default-src 'self'"
        return response

    response = make_response(render_template("matchbook.html", user=current_user, userlist=all_users))
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response

@logic.route('/messaging', methods=['GET', 'POST'])
@login_required
def messaging():
    recipient_id = current_user.focus
    recipient = User.query.filter_by(id=recipient_id).first()

    sent_history = Message.query.filter_by(sender=current_user.id, recipient=recipient.id).all()
    recv_history = Message.query.filter_by(sender=recipient.id, recipient=current_user.id).all()
    joint_history = sent_history + recv_history
    joint_history.sort(key=lambda x: x.id) # add reverse=True for descending

    form = MsgForm()

    if form.validate_on_submit():
        message = form.msg.data
        form.msg.data = ''

        new_msg_dbcall = Message(sender=current_user.id, recipient=recipient.id, message=message)
        db.session.add(new_msg_dbcall)
        db.session.commit()

        response = make_response(redirect(url_for('logic.messaging')))
        response.headers['Content-Security-Policy'] = "default-src 'self'"
        return response

    response = make_response(render_template(
        "messaging.html",
        user = current_user,
        recipient = recipient,
        msg_hist = joint_history,
        form = form
        ))
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response




@logic.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()

    if form.validate_on_submit():
        email = form.email.data
        form.email.data = ''
        challenge_passwd = form.passwd.data
        form.passwd.data = ''

        user = User.query.filter_by(email=email).first()
        if user:
            if check_password_hash(user.password, challenge_passwd):
                flash('Successful Login!', category='success')
                login_user(user, remember=True)
                return redirect(url_for('logic.profile'))
            else:
                flash('Unsucessful Login!', category='error')
        else:
            flash('Unsucessful Login!', category='error')

    
    return render_template(
            "login.html",
            user = current_user,
            form = form
            )


@logic.route('/logout')
@login_required
def logout():
    logout_user()
    response = make_response(redirect(url_for('logic.login')))
    response.headers['Content-Security-Policy'] = "default-src 'self'"
    return response

# Signup Route
@logic.route('/register', methods=['GET', 'POST'])
def register():
    pass_list = list()

    form = RegForm()

    if form.validate_on_submit():
        email = form.email.data
        firstname = form.firstname.data
        lastname = form.lastname.data
        age = form.age.data
        gender = form.gender.data
        passwd_1 = form.passwd_1.data
        passwd_2 = form.passwd_2.data

        # Basic User Input Checks
        email_check = User.query.filter_by(email=email).first()
        if len(email) < 1:
            flash('Your Email must be longer than 0 characters.', category='error')
        elif email_check:
            flash('This Email is already taken', category='error')
        else:
            pass_list.append('p')

        if len(firstname) < 1:
            flash('First name must be something', category='error')
        else:
            pass_list.append('p')

        if len(lastname) < 1:
            flash('Last name must be something', category='error')
        else:
            pass_list.append('p')

        if gender == 'M' or gender == 'F':
            pass_list.append('p')
        else:
            flash('Gender must be either M or F!', category='error')

        if len(passwd_1) < 8 or len(passwd_2) < 8:
            flash('Your Password must be longer than or equal to 8 characters.', category='error')
        else:
            if passwd_1 != passwd_2:
                flash('Your Passwords must match!', category='error')
            else:
                if len(pass_list) == 4:
                    new_user = User(email=email, firstname=firstname, lastname=lastname, age=age, gender=gender, password=generate_password_hash(passwd_2, method='sha256'))
                    db.session.add(new_user)
                    db.session.commit()
                    flash('Account Registration Successful!', category='success')
                    response = make_response(redirect(url_for('logic.profile')))
                    response.headers['Content-Security-Policy'] = "default-src 'self'"
                    return response
                else:
                    flash('Registration Failed', category='error')
    
    return render_template("register.html", user = current_user, form = form)

