from ...Dependencies.Utilities.util import *
from ...Dependencies.MongoConnection.mongoConnect import *
from .forms import *
from .User import User
from ...Dependencies.SmtpMail.SendMail import *

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

import secrets

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

new_user = User("poorna","poornakashi","poorna1999")
@auth_blueprint.route("/testAuth")
def testAuth():
    return f"Username: {new_user.username}, Email: {new_user.email},Email: {new_user.password}"

@auth_blueprint.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = auth.find_one({"email": form.email.data})
        if(auth.find_one({"email": form.email.data}) is not None):
            if user and bcrypt.check_password_hash(user['password'], form.password.data):
                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')
                    if 'result_id' in session:
                        stored_result_id = session.pop('result_id')  # Remove result_id from session
                        return redirect(url_for('agentCreate.approveAgent', result_id=stored_result_id))
                    return redirect(url_for('admin.dashboard'))
                
                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')
                if 'result_id' in session:
                    stored_result_id = session.pop('result_id')  # Remove result_id from session
                    return redirect(url_for('agentCreate.approveAgent', result_id=stored_result_id))
                return redirect(url_for('admin.dashboard'))
            else:
                flash("Password didn't match","warning")
                return redirect(url_for('authentication_blueprint.login'))
        elif(auth.find_one({"username": form.email.data}) is not None):
            user = auth.find_one({"username": form.email.data})
            if user and bcrypt.check_password_hash(user['password'], form.password.data):
                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')
                    if 'result_id' in session:
                        stored_result_id = session.pop('result_id')  # Remove result_id from session
                        return redirect(url_for('agentCreate.approveAgent', result_id=stored_result_id))
                    return redirect(url_for('admin.dashboard'))
                
                return redirect(url_for('admin.dashboard'))
            else:
                flash("Password didn't match","warning")
                return redirect(url_for('authentication_blueprint.login'))
        else:
            return redirect(url_for('authentication_blueprint.login'))


    return render_template('accounts/light_login.html',form = form)

@auth_blueprint.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        password = request.form.get('password')
        
        if not username: 
            usernameExist = True
            return render_template('accounts/profile.html', fieldsEmpty=usernameExist,message = "Username is empty")
        if not email:
            emailExist = True
            return render_template('accounts/profile.html', fieldsEmpty=emailExist,message = "EmailId is empty")
        if not password:
            passwordExist = True
            return render_template('accounts/profile.html', fieldsEmpty=passwordExist,message = "Password is empty")

        # 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)
        
        body = "Congratulations!!! You are successfully added to Opcenter Team. Kindly Save your email: "+email + " " + "password: " + password +"  (Very Confidential)"

        hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')
        new_user = User(username,email,hashed_password)
        user_details = {
            'username': new_user.username,
            'email': new_user.email,
            'password': new_user.password
        }
        auth.insert_one(user_details)
        send_mail(email,"Successfully Created User",body)

        print('Successfully added to the database')
        return "Added to the database"

    return render_template('accounts/profile.html')


@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("/deleteUsers",methods=['GET','POST'])
def deleted_users():    
    my_logger.info("................................===================================================================")
    my_logger.info("Thois is the delete user route")
    if not session.get('logged_in'):
        return redirect(url_for('authentication_blueprint.login'))
    if session.get('logged_in'):
        user = auth.find_one({"username": session['username']})
        usersSession = sessions_collection.find_one({"user_id":user['_id']})
        
        if usersSession is not None:
            checkOld = usersSession["session_id"]
            if checkOld != session["session_id"]:
                session.pop('username', None)
                session.clear()
                flash('You logged in at different device', 'warning')
                return redirect(url_for("authentication_blueprint.login"))

        else:
            session.pop('username', None)
            session.clear()
            flash('Make a new login!!!', 'warning')
            return redirect(url_for("authentication_blueprint.login"))
        
    my_logger.info(".......................This i sthe accessTest")
    my_logger.info(session['accesstype'])
    my_logger.info("...........................................The abve is the accesstype")

    if(session['accesstype'] == "admin") or (session['accesstype']=="superadmin"):
        usersInList = auth.find()

    else:
        return redirect(url_for('admin.dashboard'))

    # if(session['accesstype']!="admin") or (session['accesstype']!="superadmin"):
    #     return redirect(url_for('admin.dashboard'))

    

    Machinenames = CloudName.distinct("CloudName")
        
    return render_template("dashboard/deleteUsers.html",users = usersInList,Machinenames=Machinenames)



@auth_blueprint.route("/registerUser",methods=["GET","POST"])
def registerUser():
    print("Its coming to this route")
    if not session.get('logged_in'):
        return redirect(url_for('authentication_blueprint.login'))

    if session.get('logged_in'):
        user = auth.find_one({"username": session['username']})
        usersSession = sessions_collection.find_one({"user_id":user['_id']})
        
        if usersSession is not None:
            checkOld = usersSession["session_id"]
            if checkOld != session["session_id"]:
                session.pop('username', None)
                session.clear()
                flash('You logged in at different device', 'warning')
                return redirect(url_for("authentication_blueprint.login"))

        else:
            session.pop('username', None)
            session.clear()
            flash('Make a new login!!!', 'warning')
            return redirect(url_for("authentication_blueprint.login"))

    if(session['accesstype'] != "admin"):
        return redirect(url_for('admin.dashboard'))
    
    if(session['accesstype'] == "admin"):
        usersInList = auth.find()

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

        # 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,'accessType':accesstype})
        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'] = "User Registration Successful"
        body = "Congratulations!!! You are successfully added to Opcenter Team.\n\n"
        body += "Kindly save the following information:\n"
        body += "Email: " + email + "\n"
        body += "Password: " + password + "\n\n"
        body += "This information is confidential and should not be shared with anyone."
        message.attach(MIMEText(body, 'plain'))
        
        body += "Visit https://www.opcenterv2.parablu.com"

        smtp_session = smtplib.SMTP(smtp_server, smtp_port)
        smtp_session.starttls() 

        smtp_session.login('AKIAVZLS53X5PBNLV5GJ', 'BLPn8AcrtZTJz+BdyyTCccNQqj6UxIB/kvKMv9AWd/mB')

        smtp_session.sendmail(sender_email, email, message.as_string())
        smtp_session.quit()
        return redirect(url_for('admin.deleted_users', registration_successful=registration_successful)) 
    return redirect(url_for('admin.deleted_users', users = usersInList))



def send_reset_email(user):
    token = get_reset_token(user)
    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!!!")


@auth_blueprint.route('/reset_password',methods=['GET','POST'])
def reset_request():
    form = RequestResetForm()
    if form.validate_on_submit():
        user = auth.find_one({"email": form.email.data})
        send_reset_email(user)
        flash('An email has been sent with instructions to reset your password.','info')    
        return redirect(url_for('authentication_blueprint.login'))   
    return render_template('accounts/light_reset_request.html',title = 'Reset Password',form = form)


@auth_blueprint.route('/reset_password/<token>',methods=['GET','POST'])
def reset_token(token):
    email = verify_reset_token(token)
    if email is None:
        flash('That is an invalid or expired token','warning')
        return redirect(url_for('authentication_blueprint.reset_request'))

    form = ResetPasswordForm()
    if form.validate_on_submit():

        # 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()

        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():
        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')    
        return redirect(url_for('authentication_blueprint.login'))   
    return render_template("accounts/otpLogin.html",form = form)

def get_reset_token(user,expires_sec=1800):
    s = Serializer("IAMTHEBOSS",expires_sec)
    valueOfDump = s.dumps({'email':user['email']}).decode('utf-8')
    return valueOfDump

def verify_reset_token(token):
    s = Serializer("IAMTHEBOSS")
    try:
        email = s.loads(token)['email']
    except:
        return None
    return email