from flask import render_template, redirect, request, url_for, flash, session
from Opcenter.apps.authentication.forms import RegistrationForm,LoginForm,RequestResetForm,ResetPasswordForm
from Opcenter import bcrypt,auth,Message,app,session_manager,my_logger
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from flask import Blueprint
from functools import wraps
from datetime import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# SMTP Server configuration
smtp_server = 'email-smtp.us-east-2.amazonaws.com'
smtp_port = 587

# Sender and receiver email addresses
sender_email = 'no-reply@parablu.com'

# Email content
subject = 'Welcome to Opcenter'

auth_blueprint = Blueprint(
    'authentication_blueprint',
    __name__,
    url_prefix=''
)

def is_logged_in(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        if 'logged_in' in session:
            return f(*args, **kwargs)
        else:
            flash('Unauthorized, Please login', 'success')
            return redirect(url_for('authentication_blueprint.login'))
    return wrap



@auth_blueprint.route("/logout")
def logout():
    if session.get('logged_in'):
        user = auth.find_one({"username": session['username']})
        user_sessions = session_manager.get_user_sessions(user['_id'])
        for user_session in user_sessions:
            session_manager.destroy_session(user['_id'], user_session['session_id'])
        session.pop('username', None)
        session.clear()
        flash("You have been logged out!", "healthy")
    return redirect(url_for("authentication_blueprint.login"))


def check_logged_in():
    if session.get('logged_in'):
        user = auth.find_one({"username": session['username']})
        session_id = session.get('session_id')
        if session_manager.check_user_logged_in(user['_id'], session_id):
            session.pop('username', None)
            session.clear()
            flash('You have been logged out from another device or browser.', 'warning')
            return redirect(url_for('authentication_blueprint.login'))


@auth_blueprint.route('/')
def route_default():
    return redirect(url_for('authentication_blueprint.login'))


@auth_blueprint.route('/register', methods=['GET', 'POST'])
def register():
    if not session.get('logged_in'):
        return redirect(url_for('authentication_blueprint.login'))

    if(session['username'] != "anand"):
        return redirect(url_for('admin.dashboard'))

    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        password = request.form.get('password')
        
        # Check if user already exists in the database
        if auth.find_one({'$or': [{'username': username}, {'email': email}]}):
            user_exists = True
            return render_template('accounts/profile.html', user_exists=user_exists)

        # If user does not exist, insert into the database
        hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')  # String instead of bytes
        auth.insert_one({'username': username, 'email': email, 'password': hashed_password})
        print('Successfully added to the database')

        # Set a variable to indicate successful registration
        registration_successful = True
        message = MIMEMultipart()
        message['From'] = sender_email
        message['To'] = email
        message['Subject'] = subject
        body = "Congratulations!!! You are successfully added to Opcenter Team. Kindly Save your email: "+email + " " + "password: " + password +"  (Very Confidential)"
        message.attach(MIMEText(body, 'plain'))
        # Create a SMTP session
        smtp_session = smtplib.SMTP(smtp_server, smtp_port)
        smtp_session.starttls() # Secure the connection

        # Login with credentials
        smtp_session.login('AKIAVZLS53X5PBNLV5GJ', 'BLPn8AcrtZTJz+BdyyTCccNQqj6UxIB/kvKMv9AWd/mB')

        # Send the message via the SMTP server
        smtp_session.sendmail(sender_email, email, message.as_string())

        # Terminate the SMTP session
        smtp_session.quit()
        print("The Mail Sent Successfully!!!")
        # Render the profile page with the success message
        return render_template('accounts/profile.html', registration_successful=registration_successful)
    # If the request method is GET, render the registration form
    return render_template('accounts/profile.html')


@auth_blueprint.route('/testLogin', methods=['GET', 'POST'])
def testUserLogin():
    if request.method == 'POST':
        print("it is successfully going for the post request")
        username = request.form.get('email')
        password = request.form.get('password')
        print("the username and the password is : "+ username + "sfdsfsgd" + password
        )
    return render_template('accounts/testLogin.html', title='Login')


@auth_blueprint.route('/login', methods=['GET', 'POST'])
def login():
    print("I am login route")
    if session.get('logged_in'):
        print("The value is below")
        print(session.get('logged_in'))
        # If the user is already logged in, redirect to the dashboard
        return redirect(url_for('admin.dashboard'))
    
    form = LoginForm()
    if form.validate_on_submit():
        print("the value of the : "+ form.email.data)
        user = auth.find_one({"email": form.email.data})
        if(auth.find_one({"email": form.email.data}) is not None):
            print("This is email route")
            user = auth.find_one({"email": form.email.data})
            if user and bcrypt.check_password_hash(user['password'], form.password.data):
            # Check if the user is already logged in from another browser
                session_id = generate_session_id()
                if session_manager.check_user_logged_in(user['_id'], session_id):
                    # If the user is already logged in, log them out and display an error message
                    session_manager.logout_user(user['_id'])
                    flash('You have already logged in a different browser. And you have been logged out from the other device/browser.', 'warning')
                    session.permanent = True
                    session['logged_in'] = True
                    session['username'] = user['username']
                    session['accesstype'] = user['accessType']
                    session['logged_in_at'] = datetime.now().timestamp()
                    session['session_id'] = session_id
                    session_manager.add_session(user['_id'], session_id)
                    flash('You have been logged in!', 'success')
                    return redirect(url_for('admin.dashboard'))
                    
                # Log the user in and store the session ID in the database
                session.permanent = True
                session['logged_in'] = True
                session['username'] = user['username']
                session['accesstype'] = user['accessType']
                session['logged_in_at'] = datetime.now().timestamp()
                session['session_id'] = session_id
                session_manager.add_session(user['_id'], session_id)
                flash('You have been logged in!', 'success')
                return redirect(url_for('admin.dashboard'))


        elif(auth.find_one({"username": form.email.data}) is not None):
            print("this is the username")
            user = auth.find_one({"username": form.email.data})
            if user and bcrypt.check_password_hash(user['password'], form.password.data):
            # Check if the user is already logged in from another browser
                print("This is line 179")
                session_id = generate_session_id()
                if session_manager.check_user_logged_in(user['_id'], session_id):
                    print("This is line 182")
                    # If the user is already logged in, log them out and display an error message
                    session_manager.logout_user(user['_id'])
                    flash('You have already logged in a different browser. And you have been logged out from the other device/browser.', 'warning')
                    session.permanent = True
                    session['logged_in'] = True
                    session['username'] = user['username']
                    session['accesstype'] = user['accessType']
                    session['logged_in_at'] = datetime.now().timestamp()
                    session['session_id'] = session_id
                    session_manager.add_session(user['_id'], session_id)
                    flash('You have been logged in!', 'success')
                    return redirect(url_for('admin.dashboard'))
                
                # Log the user in and store the session ID in the database
                session.permanent = True
                session['logged_in'] = True
                session['username'] = user['username']
                session['accesstype'] = user['accessType']
                session['logged_in_at'] = datetime.now().timestamp()
                session['session_id'] = session_id
                session_manager.add_session(user['_id'], session_id)
                flash('You have been logged in!', 'success')
                return redirect(url_for('admin.dashboard'))
        
        else:
            flash('Login Unsuccessful. Please check Username/Email-Id and Password', 'danger')
            return redirect(url_for('authentication_blueprint.login'))
            
    return render_template('accounts/light_login.html', title='Login', form=form)

import secrets

def generate_session_id():
    return secrets.token_hex(16)

#Get reset token
def get_reset_token(user,expires_sec=1800):
    s = Serializer(app.config['SECRET_KEY'],expires_sec)
    my_logger.info("The email id is :"+user['email'])
    valueOfDump = s.dumps({'email':user['email']}).decode('utf-8')
    my_logger.info("the token value is :")
    my_logger.info(valueOfDump)
    return valueOfDump


def send_reset_email(user):
    token = get_reset_token(user)
    my_logger.info("The taken value in the send reset email is : ")
    my_logger.info(token)

    message = MIMEMultipart()
    message['From'] = sender_email
    message['To'] = user['email']
    message['Subject'] = "Password reset request"

    url_link = url_for('authentication_blueprint.reset_token', token=token, _external=True)
    html = render_template('accounts/email_template.html', name='Poornachandra',url_link=url_link)

    message.attach(MIMEText(html, 'html'))
    # Create a SMTP session
    smtp_session = smtplib.SMTP(smtp_server, smtp_port)
    smtp_session.starttls() # Secure the connection

    # Login with credentials
    smtp_session.login('AKIAVZLS53X5PBNLV5GJ', 'BLPn8AcrtZTJz+BdyyTCccNQqj6UxIB/kvKMv9AWd/mB')

    # Send the message via the SMTP server
    smtp_session.sendmail(sender_email, user['email'], message.as_string())

    # Terminate the SMTP session
    smtp_session.quit()
    print("The Mail Sent Successfully!!!")



#Verify reset token
def verify_reset_token(token):
    s = Serializer(app.config['SECRET_KEY'])
    try:
        email = s.loads(token)['email']
    except:
        return None
    return email



@auth_blueprint.route('/reset_password',methods=['GET','POST'])
def reset_request():
    # if session.get('logged_in'):
    #     return redirect(url_for('main.home'))
    form = RequestResetForm()
    if form.validate_on_submit():
        my_logger.info("I am in 230 line")
        my_logger.info(form.email.data)
        user = auth.find_one({"email": form.email.data})
        print(user)
        my_logger.info("The value of the user is ")
        my_logger.info(user)
        my_logger.info("Calling the Send Request Email now")
        send_reset_email(user)
        flash('An email has been sent with instructions to reset your password.','info')    
        print("Mail sent")
        return redirect(url_for('authentication_blueprint.login'))   

    return render_template('accounts/light_reset_request.html',title = 'Reset Password',form = form)


# user = verify_reset_token()

@auth_blueprint.route('/test')
def test():
    return render_template('accounts/test.html')


#Profile Image and Edits
@auth_blueprint.route('/myprofile')
def myprofile():
    return render_template("accounts/myprofile.html")

@auth_blueprint.route('/reset_password/<token>',methods=['GET','POST'])
def reset_token(token):
    email = verify_reset_token(token)
    my_logger.info("The below is the email Id after decoding the token")
    my_logger.info(email)
    if email is None:
        flash('That is an invalid or expired token','warning')
        my_logger.info("This is a invalid token because it is expired")
        return redirect(url_for('authentication_blueprint.reset_request'))

    form = ResetPasswordForm()
    if form.validate_on_submit():
        my_logger.info("the Password is coming here")
        my_logger.info(form.password.data)
        # print(form.password.data)
        hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8') #String instead of bytes
        # print(user)
        auth.update_one({'email':email},{'$set':{'password':hashed_password}})

        message = MIMEMultipart()
        message['From'] = sender_email
        message['To'] = email
        message['Subject'] = "Successfully password is reset"

        url_link = url_for('authentication_blueprint.login', _external=True)
        html = render_template('accounts/passwordUpdate.html', name='Poornachandra',Email = email,updatedPassword = form.password.data ,url_link=url_link)

        message.attach(MIMEText(html, 'html'))
        # Create a SMTP session
        smtp_session = smtplib.SMTP(smtp_server, smtp_port)
        smtp_session.starttls() # Secure the connection

        # Login with credentials
        smtp_session.login('AKIAVZLS53X5PBNLV5GJ', 'BLPn8AcrtZTJz+BdyyTCccNQqj6UxIB/kvKMv9AWd/mB')

        # Send the message via the SMTP server
        smtp_session.sendmail(sender_email, email, message.as_string())

        # Terminate the SMTP session
        smtp_session.quit()
        my_logger.info("The Mail Sent Successfully!!!")

        flash('Your password has been updated! You are now able to log in','success')
        return redirect(url_for('authentication_blueprint.login'))
    
        # return "WOrking"
    return render_template('accounts/light_reset_token.html',title = 'Reset Password',form = form)


@auth_blueprint.route('/otp_login',methods=['GET','POST'])
def otp_login():
    form = RequestResetForm()
    if form.validate_on_submit():
        my_logger.info("I am in 2307 line")
        my_logger.info(form.email.data)
        my_logger.info("The above is the value of the email address")
        user = auth.find_one({"email": form.email.data})
        if(user):
            send_reset_email(user)
            flash('An email has been sent with instructions to reset your password.','info')    
            print("Mail sent")
        return redirect(url_for('authentication_blueprint.login'))   

    return render_template("accounts/otpLogin.html",form = form)




