import os
import pathlib
from pathlib import Path
import shutil
import time
import logging
import tempfile
from typing import Union

from app.classes.controllers.crafty_perms_controller import Crafty_Perms_Controller
from app.classes.controllers.management_controller import Management_Controller
from app.classes.controllers.users_controller import Users_Controller
from app.classes.controllers.roles_controller import Roles_Controller
from app.classes.controllers.server_perms_controller import Server_Perms_Controller
from app.classes.controllers.servers_controller import Servers_Controller
from app.classes.models.server_permissions import Enum_Permissions_Server
from app.classes.models.users import helper_users
from app.classes.models.management import helpers_management
from app.classes.models.servers import servers_helper
from app.classes.shared.console import console
from app.classes.shared.helpers import helper
from app.classes.shared.server import Server
from app.classes.shared.file_helpers import file_helper
from app.classes.minecraft.server_props import ServerProps
from app.classes.minecraft.serverjars import server_jar_obj
from app.classes.minecraft.stats import Stats
from app.classes.web.websocket_helper import websocket_helper

try:
    from peewee import DoesNotExist

    # TZLocal is set as a hidden import on win pipeline
    from tzlocal import get_localzone
    from apscheduler.schedulers.background import BackgroundScheduler

except ModuleNotFoundError as err:
    helper.auto_installer_fix(err)

logger = logging.getLogger(__name__)


class Controller:
    def __init__(self):
        self.servers_list = []
        self.stats = Stats(self)
        self.crafty_perms = Crafty_Perms_Controller()
        self.management = Management_Controller()
        self.roles = Roles_Controller()
        self.server_perms = Server_Perms_Controller()
        self.servers = Servers_Controller()
        self.users = Users_Controller()
        tz = get_localzone()
        self.support_scheduler = BackgroundScheduler(timezone=str(tz))
        self.support_scheduler.start()

    def check_server_loaded(self, server_id_to_check: int):

        logger.info(f"Checking to see if we already registered {server_id_to_check}")

        for s in self.servers_list:
            known_server = s.get("server_id")
            if known_server is None:
                return False

            if known_server == server_id_to_check:
                logger.info(
                    f"skipping initialization of server {server_id_to_check} "
                    f"because it is already loaded"
                )
                return True

        return False

    def init_all_servers(self):

        servers = self.servers.get_all_defined_servers()

        for s in servers:
            server_id = s.get("server_id")

            # if we have already initialized this server, let's skip it.
            if self.check_server_loaded(server_id):
                continue

            # if this server path no longer exists - let's warn and bomb out
            if not helper.check_path_exists(
                helper.get_os_understandable_path(s["path"])
            ):
                logger.warning(
                    f"Unable to find server {s['server_name']} at path {s['path']}. "
                    f"Skipping this server"
                )

                console.warning(
                    f"Unable to find server {s['server_name']} at path {s['path']}. "
                    f"Skipping this server"
                )
                continue

            settings_file = os.path.join(
                helper.get_os_understandable_path(s["path"]), "server.properties"
            )

            # if the properties file isn't there, let's warn
            if not helper.check_file_exists(settings_file):
                logger.error(f"Unable to find {settings_file}. Skipping this server.")
                console.error(f"Unable to find {settings_file}. Skipping this server.")
                continue

            settings = ServerProps(settings_file)

            temp_server_dict = {
                "server_id": s.get("server_id"),
                "server_data_obj": s,
                "server_obj": Server(self.stats),
                "server_settings": settings.props,
            }

            # setup the server, do the auto start and all that jazz
            temp_server_dict["server_obj"].do_server_setup(s)

            # add this temp object to the list of init servers
            self.servers_list.append(temp_server_dict)

            if s["auto_start"]:
                self.servers.set_waiting_start(s["server_id"], True)

            self.refresh_server_settings(s["server_id"])

            console.info(
                f"Loaded Server: ID {s['server_id']}"
                + f" | Name: {s['server_name']}"
                + f" | Autostart: {s['auto_start']}"
                + f" | Delay: {s['auto_start_delay']} "
            )

    def refresh_server_settings(self, server_id: int):
        server_obj = self.get_server_obj(server_id)
        server_obj.reload_server_settings()

    @staticmethod
    def check_system_user():
        if helper_users.get_user_id_by_name("system") is not None:
            return True
        else:
            return False

    def set_project_root(self, root_dir):
        self.project_root = root_dir

    def package_support_logs(self, exec_user):
        if exec_user["preparing"]:
            return
        self.users.set_prepare(exec_user["user_id"])
        # pausing so on screen notifications can run for user
        time.sleep(7)
        websocket_helper.broadcast_user(
            exec_user["user_id"], "notification", "Preparing your support logs"
        )
        tempDir = tempfile.mkdtemp()
        tempZipStorage = tempfile.mkdtemp()
        full_temp = os.path.join(tempDir, "support_logs")
        os.mkdir(full_temp)
        tempZipStorage = os.path.join(tempZipStorage, "support_logs")
        crafty_path = os.path.join(full_temp, "crafty")
        os.mkdir(crafty_path)
        server_path = os.path.join(full_temp, "server")
        os.mkdir(server_path)
        if exec_user["superuser"]:
            auth_servers = self.servers.get_all_defined_servers()
        else:
            user_servers = self.servers.get_authorized_servers(
                int(exec_user["user_id"])
            )
            auth_servers = []
            for server in user_servers:
                if (
                    Enum_Permissions_Server.Logs
                    in self.server_perms.get_user_id_permissions_list(
                        exec_user["user_id"], server["server_id"]
                    )
                ):
                    auth_servers.append(server)
                else:
                    logger.info(
                        f"Logs permission not available for server "
                        f"{server['server_name']}. Skipping."
                    )
        # we'll iterate through our list of log paths from auth servers.
        for server in auth_servers:
            final_path = os.path.join(server_path, str(server["server_name"]))
            try:
                os.mkdir(final_path)
            except FileExistsError:
                final_path += "_" + server["server_uuid"]
                os.mkdir(final_path)
            try:
                file_helper.copy_file(server["log_path"], final_path)
            except Exception as e:
                logger.warning(f"Failed to copy file with error: {e}")
        # Copy crafty logs to archive dir
        full_log_name = os.path.join(crafty_path, "logs")
        file_helper.copy_dir(os.path.join(self.project_root, "logs"), full_log_name)
        self.support_scheduler.add_job(
            self.log_status,
            "interval",
            seconds=1,
            id="logs_" + str(exec_user["user_id"]),
            args=[full_temp, tempZipStorage + ".zip", exec_user],
        )
        file_helper.make_archive(tempZipStorage, tempDir)

        if len(websocket_helper.clients) > 0:
            websocket_helper.broadcast_user(
                exec_user["user_id"],
                "support_status_update",
                helper.calc_percent(full_temp, tempZipStorage + ".zip"),
            )

        tempZipStorage += ".zip"
        websocket_helper.broadcast_user(exec_user["user_id"], "send_logs_bootbox", {})

        self.users.set_support_path(exec_user["user_id"], tempZipStorage)

        self.users.stop_prepare(exec_user["user_id"])
        self.support_scheduler.remove_job("logs_" + str(exec_user["user_id"]))

    @staticmethod
    def add_system_user():
        helper_users.add_user(
            "system",
            helper.random_string_generator(64),
            "default@example.com",
            False,
            False,
        )

    def get_server_settings(self, server_id):
        for s in self.servers_list:
            if int(s["server_id"]) == int(server_id):
                return s["server_settings"]

        logger.warning(f"Unable to find server object for server id {server_id}")
        return False

    def crash_detection(self, server_obj):
        svr = self.get_server_obj(server_obj.server_id)
        # start or stop crash detection depending upon user preference
        # The below functions check to see if the server is running.
        # They only execute if it's running.
        if server_obj.crash_detection == 1:
            svr.start_crash_detection()
        else:
            svr.stop_crash_detection()

    def log_status(self, source_path, dest_path, exec_user):
        results = helper.calc_percent(source_path, dest_path)
        self.log_stats = results

        if len(websocket_helper.clients) > 0:
            websocket_helper.broadcast_user(
                exec_user["user_id"], "support_status_update", results
            )

    def send_log_status(self):
        try:
            return self.log_stats
        except:
            return {"percent": 0, "total_files": 0}

    def get_server_obj(self, server_id: Union[str, int]) -> Union[bool, Server]:
        for s in self.servers_list:
            if str(s["server_id"]) == str(server_id):
                return s["server_obj"]

        logger.warning(f"Unable to find server object for server id {server_id}")
        return False  # TODO: Change to None

    def get_server_data(self, server_id: str):
        for s in self.servers_list:
            if str(s["server_id"]) == str(server_id):
                return s["server_data_obj"]

        logger.warning(f"Unable to find server object for server id {server_id}")
        return False

    @staticmethod
    def list_defined_servers():
        servers = servers_helper.get_all_defined_servers()
        return servers

    def list_running_servers(self):
        running_servers = []

        # for each server
        for s in self.servers_list:

            # is the server running?
            srv_obj = s["server_obj"]
            running = srv_obj.check_running()
            # if so, let's add a dictionary to the list of running servers
            if running:
                running_servers.append({"id": srv_obj.server_id, "name": srv_obj.name})

        return running_servers

    def stop_all_servers(self):
        servers = self.list_running_servers()
        logger.info(f"Found {len(servers)} running server(s)")
        console.info(f"Found {len(servers)} running server(s)")

        logger.info("Stopping All Servers")
        console.info("Stopping All Servers")

        for s in servers:
            logger.info(f"Stopping Server ID {s['id']} - {s['name']}")
            console.info(f"Stopping Server ID {s['id']} - {s['name']}")

            self.stop_server(s["id"])

            # let's wait 2 seconds to let everything flush out
            time.sleep(2)

        logger.info("All Servers Stopped")
        console.info("All Servers Stopped")

    def stop_server(self, server_id):
        # issue the stop command
        svr_obj = self.get_server_obj(server_id)
        svr_obj.stop_threaded_server()

    def create_jar_server(
        self,
        server: str,
        version: str,
        name: str,
        min_mem: int,
        max_mem: int,
        port: int,
    ):
        server_id = helper.create_uuid()
        server_dir = os.path.join(helper.servers_dir, server_id)
        backup_path = os.path.join(helper.backup_path, server_id)
        if helper.is_os_windows():
            server_dir = helper.wtol_path(server_dir)
            backup_path = helper.wtol_path(backup_path)
            server_dir.replace(" ", "^ ")
            backup_path.replace(" ", "^ ")

        server_file = f"{server}-{version}.jar"
        full_jar_path = os.path.join(server_dir, server_file)

        # make the dir - perhaps a UUID?
        helper.ensure_dir_exists(server_dir)
        helper.ensure_dir_exists(backup_path)

        try:
            # do a eula.txt
            with open(os.path.join(server_dir, "eula.txt"), "w", encoding="utf-8") as f:
                f.write("eula=false")
                f.close()

            # setup server.properties with the port
            with open(
                os.path.join(server_dir, "server.properties"), "w", encoding="utf-8"
            ) as f:
                f.write(f"server-port={port}")
                f.close()

        except Exception as e:
            logger.error(f"Unable to create required server files due to :{e}")
            return False

        if helper.is_os_windows():
            server_command = (
                f"java -Xms{helper.float_to_string(min_mem)}M "
                f"-Xmx{helper.float_to_string(max_mem)}M "
                f'-jar "{full_jar_path}" nogui'
            )
        else:
            server_command = (
                f"java -Xms{helper.float_to_string(min_mem)}M "
                f"-Xmx{helper.float_to_string(max_mem)}M "
                f"-jar {full_jar_path} nogui"
            )
        server_log_file = f"{server_dir}/logs/latest.log"
        server_stop = "stop"

        new_id = self.register_server(
            name,
            server_id,
            server_dir,
            backup_path,
            server_command,
            server_file,
            server_log_file,
            server_stop,
            port,
            server_type="minecraft-java",
        )

        # download the jar
        server_jar_obj.download_jar(server, version, full_jar_path, new_id)

        return new_id

    @staticmethod
    def verify_jar_server(server_path: str, server_jar: str):
        server_path = helper.get_os_understandable_path(server_path)
        path_check = helper.check_path_exists(server_path)
        jar_check = helper.check_file_exists(os.path.join(server_path, server_jar))
        if not path_check or not jar_check:
            return False
        return True

    @staticmethod
    def verify_zip_server(zip_path: str):
        zip_path = helper.get_os_understandable_path(zip_path)
        zip_check = helper.check_file_exists(zip_path)
        if not zip_check:
            return False
        return True

    def import_jar_server(
        self,
        server_name: str,
        server_path: str,
        server_jar: str,
        min_mem: int,
        max_mem: int,
        port: int,
    ):
        server_id = helper.create_uuid()
        new_server_dir = os.path.join(helper.servers_dir, server_id)
        backup_path = os.path.join(helper.backup_path, server_id)
        if helper.is_os_windows():
            new_server_dir = helper.wtol_path(new_server_dir)
            backup_path = helper.wtol_path(backup_path)
            new_server_dir.replace(" ", "^ ")
            backup_path.replace(" ", "^ ")

        helper.ensure_dir_exists(new_server_dir)
        helper.ensure_dir_exists(backup_path)
        server_path = helper.get_os_understandable_path(server_path)
        try:
            file_helper.copy_dir(server_path, new_server_dir, True)
        except shutil.Error as ex:
            logger.error(f"Server import failed with error: {ex}")

        has_properties = False
        for item in os.listdir(new_server_dir):
            if str(item) == "server.properties":
                has_properties = True
        if not has_properties:
            logger.info(
                f"No server.properties found on zip file import. "
                f"Creating one with port selection of {str(port)}"
            )
            with open(
                os.path.join(new_server_dir, "server.properties"), "w", encoding="utf-8"
            ) as f:
                f.write(f"server-port={port}")
                f.close()

        full_jar_path = os.path.join(new_server_dir, server_jar)

        if helper.is_os_windows():
            server_command = (
                f"java -Xms{helper.float_to_string(min_mem)}M "
                f"-Xmx{helper.float_to_string(max_mem)}M "
                f'-jar "{full_jar_path}" nogui'
            )
        else:
            server_command = (
                f"java -Xms{helper.float_to_string(min_mem)}M "
                f"-Xmx{helper.float_to_string(max_mem)}M "
                f"-jar {full_jar_path} nogui"
            )
        server_log_file = f"{new_server_dir}/logs/latest.log"
        server_stop = "stop"

        new_id = self.register_server(
            server_name,
            server_id,
            new_server_dir,
            backup_path,
            server_command,
            server_jar,
            server_log_file,
            server_stop,
            port,
            server_type="minecraft-java",
        )
        return new_id

    def import_zip_server(
        self,
        server_name: str,
        zip_path: str,
        server_jar: str,
        min_mem: int,
        max_mem: int,
        port: int,
    ):
        server_id = helper.create_uuid()
        new_server_dir = os.path.join(helper.servers_dir, server_id)
        backup_path = os.path.join(helper.backup_path, server_id)
        if helper.is_os_windows():
            new_server_dir = helper.wtol_path(new_server_dir)
            backup_path = helper.wtol_path(backup_path)
            new_server_dir.replace(" ", "^ ")
            backup_path.replace(" ", "^ ")

        tempDir = helper.get_os_understandable_path(zip_path)
        helper.ensure_dir_exists(new_server_dir)
        helper.ensure_dir_exists(backup_path)
        has_properties = False
        # extracts archive to temp directory
        for item in os.listdir(tempDir):
            if str(item) == "server.properties":
                has_properties = True
            try:
                if not os.path.isdir(os.path.join(tempDir, item)):
                    file_helper.move_file(
                        os.path.join(tempDir, item), os.path.join(new_server_dir, item)
                    )
                else:
                    file_helper.move_dir(
                        os.path.join(tempDir, item), os.path.join(new_server_dir, item)
                    )
            except Exception as ex:
                logger.error(f"ERROR IN ZIP IMPORT: {ex}")
        if not has_properties:
            logger.info(
                f"No server.properties found on zip file import. "
                f"Creating one with port selection of {str(port)}"
            )
            with open(
                os.path.join(new_server_dir, "server.properties"), "w", encoding="utf-8"
            ) as f:
                f.write(f"server-port={port}")
                f.close()

        full_jar_path = os.path.join(new_server_dir, server_jar)

        if helper.is_os_windows():
            server_command = (
                f"java -Xms{helper.float_to_string(min_mem)}M "
                f"-Xmx{helper.float_to_string(max_mem)}M "
                f'-jar "{full_jar_path}" nogui'
            )
        else:
            server_command = (
                f"java -Xms{helper.float_to_string(min_mem)}M "
                f"-Xmx{helper.float_to_string(max_mem)}M "
                f"-jar {full_jar_path} nogui"
            )
        logger.debug("command: " + server_command)
        server_log_file = f"{new_server_dir}/logs/latest.log"
        server_stop = "stop"

        new_id = self.register_server(
            server_name,
            server_id,
            new_server_dir,
            backup_path,
            server_command,
            server_jar,
            server_log_file,
            server_stop,
            port,
            server_type="minecraft-java",
        )
        return new_id

    # **********************************************************************************
    #                                   BEDROCK IMPORTS
    # **********************************************************************************

    def import_bedrock_server(
        self, server_name: str, server_path: str, server_exe: str, port: int
    ):
        server_id = helper.create_uuid()
        new_server_dir = os.path.join(helper.servers_dir, server_id)
        backup_path = os.path.join(helper.backup_path, server_id)
        if helper.is_os_windows():
            new_server_dir = helper.wtol_path(new_server_dir)
            backup_path = helper.wtol_path(backup_path)
            new_server_dir.replace(" ", "^ ")
            backup_path.replace(" ", "^ ")

        helper.ensure_dir_exists(new_server_dir)
        helper.ensure_dir_exists(backup_path)
        server_path = helper.get_os_understandable_path(server_path)
        try:
            file_helper.copy_dir(server_path, new_server_dir, True)
        except shutil.Error as ex:
            logger.error(f"Server import failed with error: {ex}")

        has_properties = False
        for item in os.listdir(new_server_dir):
            if str(item) == "server.properties":
                has_properties = True
        if not has_properties:
            logger.info(
                f"No server.properties found on zip file import. "
                f"Creating one with port selection of {str(port)}"
            )
            with open(
                os.path.join(new_server_dir, "server.properties"), "w", encoding="utf-8"
            ) as f:
                f.write(f"server-port={port}")
                f.close()

        full_jar_path = os.path.join(new_server_dir, server_exe)

        if helper.is_os_windows():
            server_command = f'"{full_jar_path}"'
        else:
            server_command = f"./{server_exe}"
        logger.debug("command: " + server_command)
        server_log_file = "N/A"
        server_stop = "stop"

        new_id = self.register_server(
            server_name,
            server_id,
            new_server_dir,
            backup_path,
            server_command,
            server_exe,
            server_log_file,
            server_stop,
            port,
            server_type="minecraft-bedrock",
        )
        if os.name != "nt":
            if helper.check_file_exists(full_jar_path):
                os.chmod(full_jar_path, 0o2775)
        return new_id

    def import_bedrock_zip_server(
        self, server_name: str, zip_path: str, server_exe: str, port: int
    ):
        server_id = helper.create_uuid()
        new_server_dir = os.path.join(helper.servers_dir, server_id)
        backup_path = os.path.join(helper.backup_path, server_id)
        if helper.is_os_windows():
            new_server_dir = helper.wtol_path(new_server_dir)
            backup_path = helper.wtol_path(backup_path)
            new_server_dir.replace(" ", "^ ")
            backup_path.replace(" ", "^ ")

        tempDir = helper.get_os_understandable_path(zip_path)
        helper.ensure_dir_exists(new_server_dir)
        helper.ensure_dir_exists(backup_path)
        has_properties = False
        # extracts archive to temp directory
        for item in os.listdir(tempDir):
            if str(item) == "server.properties":
                has_properties = True
            try:
                if not os.path.isdir(os.path.join(tempDir, item)):
                    file_helper.move_file(
                        os.path.join(tempDir, item), os.path.join(new_server_dir, item)
                    )
                else:
                    file_helper.move_dir(
                        os.path.join(tempDir, item), os.path.join(new_server_dir, item)
                    )
            except Exception as ex:
                logger.error(f"ERROR IN ZIP IMPORT: {ex}")
        if not has_properties:
            logger.info(
                f"No server.properties found on zip file import. "
                f"Creating one with port selection of {str(port)}"
            )
            with open(
                os.path.join(new_server_dir, "server.properties"), "w", encoding="utf-8"
            ) as f:
                f.write(f"server-port={port}")
                f.close()

        full_jar_path = os.path.join(new_server_dir, server_exe)

        if helper.is_os_windows():
            server_command = f'"{full_jar_path}"'
        else:
            server_command = f"./{server_exe}"
        logger.debug("command: " + server_command)
        server_log_file = "N/A"
        server_stop = "stop"

        new_id = self.register_server(
            server_name,
            server_id,
            new_server_dir,
            backup_path,
            server_command,
            server_exe,
            server_log_file,
            server_stop,
            port,
            server_type="minecraft-bedrock",
        )
        if os.name != "nt":
            if helper.check_file_exists(full_jar_path):
                os.chmod(full_jar_path, 0o2775)

        return new_id

    # **********************************************************************************
    #                                   BEDROCK IMPORTS END
    # **********************************************************************************

    def rename_backup_dir(self, old_server_id, new_server_id, new_uuid):
        server_data = self.servers.get_server_data_by_id(old_server_id)
        old_bu_path = server_data["backup_path"]
        Server_Perms_Controller.backup_role_swap(old_server_id, new_server_id)
        if not helper.is_os_windows():
            backup_path = helper.validate_traversal(helper.backup_path, old_bu_path)
        if helper.is_os_windows():
            backup_path = helper.validate_traversal(
                helper.wtol_path(helper.backup_path), helper.wtol_path(old_bu_path)
            )
            backup_path = helper.wtol_path(str(backup_path))
            backup_path.replace(" ", "^ ")
            backup_path = Path(backup_path)
        backup_path_components = list(backup_path.parts)
        backup_path_components[-1] = new_uuid
        new_bu_path = pathlib.PurePath(os.path.join(*backup_path_components))
        if os.path.isdir(new_bu_path):
            if helper.validate_traversal(helper.backup_path, new_bu_path):
                os.rmdir(new_bu_path)
        backup_path.rename(new_bu_path)

    def register_server(
        self,
        name: str,
        server_uuid: str,
        server_dir: str,
        backup_path: str,
        server_command: str,
        server_file: str,
        server_log_file: str,
        server_stop: str,
        server_port: int,
        server_type: str,
    ):
        # put data in the db

        new_id = self.servers.create_server(
            name,
            server_uuid,
            server_dir,
            backup_path,
            server_command,
            server_file,
            server_log_file,
            server_stop,
            server_type,
            server_port,
        )

        if not helper.check_file_exists(os.path.join(server_dir, "crafty_managed.txt")):
            try:
                # place a file in the dir saying it's owned by crafty
                with open(
                    os.path.join(server_dir, "crafty_managed.txt"),
                    "w",
                    encoding="utf-8",
                ) as f:
                    f.write(
                        "The server is managed by Crafty Controller.\n "
                        "Leave this directory/files alone please"
                    )
                    f.close()

            except Exception as e:
                logger.error(f"Unable to create required server files due to :{e}")
                return False

        # let's re-init all servers
        self.init_all_servers()

        return new_id

    def remove_server(self, server_id, files):
        counter = 0
        for s in self.servers_list:

            # if this is the droid... im mean server we are looking for...
            if str(s["server_id"]) == str(server_id):
                server_data = self.get_server_data(server_id)
                server_name = server_data["server_name"]

                logger.info(f"Deleting Server: ID {server_id} | Name: {server_name} ")
                console.info(f"Deleting Server: ID {server_id} | Name: {server_name} ")

                srv_obj = s["server_obj"]
                running = srv_obj.check_running()

                if running:
                    self.stop_server(server_id)
                if files:
                    try:
                        file_helper.del_dirs(
                            helper.get_os_understandable_path(
                                self.servers.get_server_data_by_id(server_id)["path"]
                            )
                        )
                    except Exception as e:
                        logger.error(
                            f"Unable to delete server files for server with ID: "
                            f"{server_id} with error logged: {e}"
                        )
                    if helper.check_path_exists(
                        self.servers.get_server_data_by_id(server_id)["backup_path"]
                    ):
                        file_helper.del_dirs(
                            helper.get_os_understandable_path(
                                self.servers.get_server_data_by_id(server_id)[
                                    "backup_path"
                                ]
                            )
                        )

                # Cleanup scheduled tasks
                try:
                    helpers_management.delete_scheduled_task_by_server(server_id)
                except DoesNotExist:
                    logger.info("No scheduled jobs exist. Continuing.")
                # remove the server from the DB
                self.servers.remove_server(server_id)

                # remove the server from servers list
                self.servers_list.pop(counter)

            counter += 1

    @staticmethod
    def clear_unexecuted_commands():
        helpers_management.clear_unexecuted_commands()

    @staticmethod
    def clear_support_status():
        helper_users.clear_support_status()
