import os
import re
import time
from datetime import datetime
from subprocess import run
import json

CHANGES_REQUIRING_RESTART = ['wifi_password', 'ssid', 'enable_access_point', 'enable_chat', 'enable_deltachat', 'butterbox_hostname', 'ssh_access_settings', 'root_account_settings']

def lock_root_account():
    check_usr = run(["sudo", "passwd", "-S", "root"], capture_output = True, text = True)
    if ' L ' in check_usr.stdout:
        print(f"Root account already locked")
        return False
    print(f"Root account not locked, trying to lock it.")
    if not load_setting('root_password'):
        print(f"Root account has no password, setting one before locking it.")
        # password must be empty so we set it to be 'root' before locking the account
        result_set_dummy_password = run(["sudo", "passwd", "-s", "root"], capture_output = True, text = True, input="root")
        print(result_set_dummy_password)
        if result_set_dummy_password.returncode !=0:
            print(f"Issue setting dummy pass for root account")
            print(result_set_dummy_password)
            return False 
    else:
        print(f"running the lock command now")
        result_lock = run(["sudo", "passwd", "-l", "root"], capture_output = True, text = True)
        if result_lock.returncode != 0:
            print(f"Issue locking root account")
            print(result_lock)
            return False
        print(f"Root account now locked.")
        return True
    
def set_root_password(new_pass):
    check_usr = run(["sudo", "passwd", "-S", "root"], capture_output = True, text = True)
    if ' L ' in check_usr.stdout:
        print(f"Root account locked, unlocking...")
        unlock_result = run(["sudo", "passwd", "-u", "root"], capture_output = True, text = True)
        if unlock_result.returncode != 0:
            print(f"Issue unlocking root account")
            print(unlock_result)
            return False
    else:
        result = run(["passwd", "-s", "root"], capture_output = True, text = True, input=new_pass)
        if result.returncode != 0:
            print(f"Issue setting password for root account")
            print(result)
            return False
        else:
            print(f"Root account password set successfully.")
            return True

def enable_service(service: str):
    is_enabled = run(["sudo", "systemctl", "is-enabled", service], capture_output = True, text = True)
    if 'found' in is_enabled.stdout:
        print(f"Service {service} not found")
        return False
    if 'disabled' in is_enabled.stdout:
        enable = run(["sudo", "systemctl", "enable", service], capture_output = True, text = True)
        if enable.returncode != 0:
            print(f"Issue enabling service {service}:")
            print(enable)
            return False
    else:
        print(f"Service {service} already enabled")
        return False
    print(f"Service {service} has been enabled.")
    return True

def disable_service(service: str):
    is_enabled = run(["sudo", "systemctl", "is-enabled", service], capture_output = True, text = True)
    if 'found' in is_enabled.stdout:
        print(f"Service {service} not found")
        return False
    if 'enabled' in is_enabled.stdout:
        enable = run(["sudo", "systemctl", "disable", service])
        print(enable)
        if enable.returncode != 0:
            print(f"issue disabling service {service}:")
            print(enable)
            return False
    else:
        print(f"Service {service} already disabled")
        return False
    return True

def load_setting(setting):
    with open("./settings.txt", "r") as f:
        settings = json.load(f)
    try:
        return settings[setting]
    except:
        return None

def change_service_status(setting, service):
    if load_setting(setting) == "true":
        return(enable_service(service))
    else:
        return(disable_service(service))

def change_line_in_file(target_file: str, regex: str, replacement: str):
    regex = re.compile(regex)
    if not os.path.isfile(target_file):
        raise FileNotFoundError(f"File {target_file} does not exist")
    else:
        changed = False
        with open(target_file, "r") as f:
            lines = f.readlines()
            if not lines:
                print(f"File {target_file} empty")
                return False
            for i, line in enumerate(lines):
                match = re.fullmatch(replacement, line)
                if match:
                    print(f"Line already exists, not changing.")
                    return False
            for i, line in enumerate(lines):
                match = re.fullmatch(regex, line)
                if match:
                    lines[i] = replacement
                    changed = True
        new_lines = "".join(lines)
        if not changed:
            print(f"Can't match line: {regex}, adding it to the end of target file {target_file}!")
            new_lines += replacement
        with open(target_file, "w") as f:
            print(f"Writing changed line to file {target_file}.")
            f.write(new_lines)
            return True


def check_settings(raspap_installed: bool):
    if not os.path.exists("./settings.txt"):
        return
    last_modified = os.path.getmtime('./settings.txt')
    diff_in_minutes = (datetime.now().timestamp() - last_modified)/60
    needs_restart = False
    if diff_in_minutes < 1:
        for s in CHANGES_REQUIRING_RESTART:
            print(f"Now at setting: {s}")
            if s == "wifi_password" and raspap_installed:
                regex_wpa_method = "wpa=.*?\n"
                if load_setting("wifi_password") == "":
                    needs_restart = change_line_in_file("/etc/hostapd/hostapd.conf", regex_wpa_method, f"wpa=none\n") or needs_restart
                else:
                    needs_restart = change_line_in_file("/etc/hostapd/hostapd.conf", regex_wpa_method, f"wpa=3\n") or needs_restart
                    regex_pass = "wpa_passphrase=.*?\n"
                    needs_restart = change_line_in_file("/etc/hostapd/hostapd.conf", regex_pass,
                                        f"wpa_passphrase={load_setting("wifi_password")}\n") or needs_restart

            if s == "ssid" and raspap_installed:
                regex_ssid = "ssid=.*?\n"
                needs_restart = change_line_in_file("/etc/hostapd/hostapd.conf", regex_ssid, f"ssid={load_setting("ssid")}\n") or needs_restart
            if s == "enable_chat":
                needs_restart = change_service_status("enable_chat", "dendrite") or needs_restart
            if s == "enable_access_point" and raspap_installed:
                needs_restart = change_service_status("enable_access_point", "raspapd") or needs_restart
            if s == "enable_deltachat":
                needs_restart = change_service_status("enable_deltachat", "maddy") or needs_restart
            if s == "butterbox_hostname":
               # change in  /etc/hostname
                print("Writing new hostname to /etc/hostname")
                with open("/etc/hostname", 'w') as f:
                    f.write(load_setting('butterbox_hostname'))
                    f.write("\n")
                # change in nginx.conf
                regex_nginx_server = "        server_name.*?.local;\n"
                replacement = f"        server_name {load_setting('butterbox_hostname')}.local;\n"
                
                result_nginx = change_line_in_file("/etc/nginx/sites-available/default", regex_nginx_server, replacement)
                needs_restart = needs_restart or result_nginx

                # change in butterbox-dnsmasq.conf
                if  raspap_installed:
                    regex_dns = "address=/.*?.local/10.3.141.1\n"
                    result = change_line_in_file("/etc/dnsmasq.d/butterbox-dnsmasq.conf", regex_dns,
                                        f"address=/{load_setting("butterbox_hostname")}.local/10.3.141.1\n")
                    print(f"Changing dnsmasq config: {result}")
                    needs_restart = needs_restart or result
            if s == "ssh_access_settings":
               if load_setting("ssh_access_settings") == "disable_ssh":
                   needs_restart = disable_service('ssh') or needs_restart
               if load_setting("ssh_access_settings") == "enable_ssh_with_root_password":
                   print("looking at the service")
                   needs_restart = enable_service('ssh') or needs_restart
                   print("now looking at the password line")
                   regex_password_auth = "PasswordAuthentication.*?\n"
                   needs_restart = change_line_in_file("/etc/ssh/sshd_config", regex_password_auth,
                                       f"PasswordAuthentication yes\n") or needs_restart
                   print("now looking at the permit login line")
                   regex_root_login = "PermitRootLogin.*?\n"
                   needs_restart = change_line_in_file("/etc/ssh/sshd_config", regex_root_login,
                                       f"PermitRootLogin yes\n") or needs_restart
#               elif load_setting("ssh_access_settings") == "enable_ssh_with_public_key":
#                   needs_restart = needs_restart or enable_service('ssh')
#                   regex_password_auth = "PasswordAuthentication.*?\n"
#                   needs_restart = needs_restart or change_line_in_file("/etc/ssh/sshd_config", regex_password_auth,
#                                       f"PasswordAuthentication no\n")
#                   regex_root_login = "PermitRootLogin.*?\n"
#                   needs_restart = needs_restart or change_line_in_file("/etc/ssh/sshd_config", regex_root_login,
#                                       f"PermitRootLogin prohibit-password\n")
#                   if load_setting('ssh_key'):
#                       regex_key =  f"{load_setting('ssh_key')}\n"
#                       needs_restart = needs_restart or change_line_in_file("/home/root/.ssh/authorized_keys", regex_key,
#                                                                            regex_key)
                   # append here new key!!!
            if s == "root_account_settings":
                setting = load_setting("root_account_settings")
                print(setting)
                if setting == "lock_root_account":
                    needs_restart =  lock_root_account() or needs_restart
                elif setting == "set_root_password":
                    if load_setting('root_password'):
                        print("will set root password...")
                        needs_restart = set_root_password(load_setting('root_password')) or needs_restart
    if needs_restart:
        print("I am restarting here")
        time.sleep(60)
        run(["sudo", "reboot"])

if __name__ ==  "__main__":
    raspap_installed = os.path.exists("/var/www/html/raspap")
    while True:
        print("Sleep 10 sec")
        check_settings(raspap_installed)
        time.sleep(10)

