from flask import Flask, render_template, request, redirect, url_for, make_response
import bcrypt
import sqlite3
import configparser
import subprocess
import os
import re
from waitress import serve

# Load from config.ini

config = configparser.ConfigParser()
config.read("../config.ini")
database = config.get("Account", "database")
runport = config.get("Account", "port")

# Status report

print("HectaMail Account Service is starting up...")
print("Your database is located at:", database)

allowed_pattern = r'^[a-zA-Z0-9.]+$'

def is_valid_input(input_string):
    return re.match(allowed_pattern, input_string) is not None

app = Flask(__name__)

def change_email_password(username, password):
    if password and is_valid_input(username):
        try:

            # Create a temporary file to escape the password

            with open("../tmp/chnpassword.tmp", "w") as file:
                file.write(password)

            # Pass the file through a shell command
            cmd = ["cat", "../tmp/chnpassword.tmp", "|", "maddy", "creds", "password", f"{username}@hectabit.org"]

            # Run and determine the result of the shell command
            result = subprocess.run(" ".join(cmd), shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

            # Delete the temporary file
            os.remove("../tmp/chnpassword.tmp")


            # Check if command executed correctly
            if result.returncode == 0:
                # Command executed successfully
                return True
            else:
                # Handle errors, log them, and return False
                error_message = result.stderr.decode("utf-8")
                print(f"Error creating email account: {error_message}")
                return False
        except Exception as e:
            # Handle exceptions and return False
            print(f"Error creating email account: {str(e)}")
            return False
    else:
        # Something went very wrong if this function triggers
        print(f"Injection Bypass! Very bad!")
        return False


def fetch_hash_from_database(key):
    conn = sqlite3.connect(database)
    cursor = conn.cursor()
    cursor.execute("SELECT value FROM passwords WHERE key = ?", (key,))
    result = cursor.fetchone()
    conn.close()

    if result:
        return result[0][7:]  # Remove the first 7 characters
    else:
        return None

def verify_bcrypt(passphrase, hashed_password):
    return bcrypt.checkpw(passphrase.encode('utf-8'), hashed_password.encode('utf-8'))

@app.route('/')
def index():
    email = request.cookies.get('email')
    if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'):
        return render_template('dashboard.html', user_email=email)
    else:
        return render_template('index.html')

@app.route('/loginapi', methods=['POST'])
def login():
    key_to_fetch = request.form['email']
    password_to_check = request.form['password']

    passwordhash = fetch_hash_from_database(key_to_fetch)

    if passwordhash:
        is_password_valid = verify_bcrypt(password_to_check, passwordhash)
        if is_password_valid:
            response = make_response(redirect('/account'))
            response.set_cookie('passwordhash', passwordhash)
            response.set_cookie('email', request.form['email'])
            return response
        else:
            return render_template('wrong.html')
    else:
        return render_template('wrong.html')

@app.route('/deleteapi', methods=['POST'])
def delete():
    key_to_fetch = request.form['email']
    verify_hash = request.form['hash']

    passwordhash = fetch_hash_from_database(key_to_fetch)

    if passwordhash:
        if verify_hash == passwordhash:
            cmd = ["echo", "y", "|", "maddy", "creds", "remove", key_to_fetch]
            result = subprocess.run(" ".join(cmd), shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

            if result.returncode == 0:
                # Command executed successfully
                response = make_response(redirect('/'))
                response.set_cookie('passwordhash', '', expires=0)
                response.set_cookie('email', '', expires=0)
                return response
            else:
                # Handle errors, log them, and return False
                error_message = result.stderr.decode("utf-8")
                print(f"Error deleting email account: {error_message}")
                return render_template('err.html')

        else:
            return render_template('wrong.html')
    else:
        return render_template('wrong.html')

@app.route('/deleteacct')
def deleteacct():
    email = request.cookies.get('email')
    passwordhash = request.cookies.get('passwordhash')
    if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'):
        return render_template('confirm.html', user_email=email, password_hash=passwordhash)
    else:
        return redirect('/account')

@app.route('/logout')
def logout():
    response = make_response(redirect('/'))
    response.set_cookie('passwordhash', '', expires=0)
    response.set_cookie('email', '', expires=0)
    return response

@app.route('/changepass')
def changepass():
    email = request.cookies.get('email')
    passwordhash = request.cookies.get('passwordhash')
    if 'passwordhash' in request.cookies and request.cookies.get('passwordhash'):
        return render_template('changepass.html', user_email=email, password_hash=passwordhash)
    else:
        return redirect('/account')

@app.route('/changeapi', methods=['POST'])
def register():
    # Get the form data
    username = request.form.get('email')
    verifyhash = request.form.get('passwordhash')
    password = request.form.get('password')

    passwordhash = fetch_hash_from_database(username)

    if verifyhash == passwordhash:
        # Attempt to change the password
        if change_email_password(username, password):
            # Password changed
            response.set_cookie('passwordhash', '', expires=0)
            response.set_cookie('email', '', expires=0)
            return redirect('/account')
        else:
            # Backend error, potentially maddy
            return render_template('err.html'), 500
    else:
        return render_template('wrong.html'), 400

if __name__ == '__main__':
    serve(app, host='0.0.0.0', port=runport)
