import subprocess
import click
import time
import keyboard
import sys
import os
from datetime import datetime
import shutil
from pathlib import Path
import yaml

from config_manager import load_config, save_config
from command_executor import (
    verify_appimage, manage_services, hide_mouse,
    execute_pre_launch, launch_appimage, compute_md5
)

APPIMAGE_PATH = "./TrioMedical.AppImage"
SILENT_MODE_TIMEOUT = 5
INTERRUPT_KEYS = ["enter"]
SERVICE_FILE = "/etc/systemd/system/launcher.service"
TEMPLATE_PATH = os.path.join(os.path.dirname(__file__), "templates", "launcher.service.template")
CONFIG_FILE = "launcher_config.yaml"

def get_config_paths():
    """Return a list of LXDE-pi configuration paths to back up."""
    home = Path.home()
    config_paths = [
        home / ".config/lxpanel",
        home / ".config/lxsession",
        home / ".config/pcmanfm",
        home / ".config/lxterminal",
        home / ".config/openbox",
        home / ".config/libfm",
        home / ".config/menus"
    ]
    return [path for path in config_paths if path.exists()]

def create_backup():
    """Copy LXDE-pi configuration folders to a backup directory, skipping missing ones."""
    try:
        backup_dir = Path(__file__).parent.resolve() / "backups"
        if not os.access(backup_dir, os.W_OK):
            click.echo(f"Error: No write permission for backup directory {backup_dir}")
            return None
        if shutil.disk_usage(backup_dir).free < 1024 * 1024:  # Require at least 1MB free
            click.echo("Error: Insufficient disk space for backup")
            return None
        backup_dir.mkdir(parents=True, exist_ok=True)

        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_folder = backup_dir / f"lxde_backup_{timestamp}"
        backup_folder.mkdir(exist_ok=True)

        files_added = False
        for config_path in get_config_paths():
            if config_path.exists() and config_path.is_dir():
                click.echo(f"Processing directory: {config_path}")
                dest_path = backup_folder / config_path.relative_to(Path.home())
                try:
                    shutil.copytree(config_path, dest_path, dirs_exist_ok=True)
                    click.echo(f"Successfully backed up: {config_path} to {dest_path}")
                    files_added = True
                except (PermissionError, OSError) as e:
                    click.echo(f"Error backing up {config_path}: {str(e)}")
                    continue
            else:
                click.echo(f"Skipping {config_path}: Directory does not exist or is not a directory")

        if not files_added:
            click.echo("No directories were copied to the backup directory. Deleting empty directory.")
            shutil.rmtree(backup_folder, ignore_errors=True)
            return None

        click.echo(f"Backup created successfully: {backup_folder}")
        return str(backup_folder)
    except Exception as e:
        click.echo(f"Error during backup: {str(e)}")
        if 'backup_folder' in locals():
            shutil.rmtree(backup_folder, ignore_errors=True)
        return None

def restore_backup(backup_folder, restart_services=True):
    """Restore only the LXDE-pi configuration directories present in the backup folder."""
    try:
        backup_folder = Path(backup_folder)
        if not backup_folder.exists():
            click.echo(f"Backup directory not found: {backup_folder}")
            return False
        if not backup_folder.is_dir():
            click.echo(f"Backup path is not a directory: {backup_folder}")
            return False

        config_paths = get_config_paths()
        restored = False
        for config_path in config_paths:
            temp_config_path = backup_folder / config_path.relative_to(Path.home())
            if temp_config_path.exists() and temp_config_path.is_dir():
                if config_path.exists():
                    shutil.rmtree(config_path)
                shutil.copytree(temp_config_path, config_path, dirs_exist_ok=True)
                click.echo(f"Restored: {config_path}")
                restored = True
            else:
                click.echo(f"Skipping {config_path}: Not found in backup directory")

        if not restored:
            click.echo("No directories were restored from the backup.")
            return False

        if restart_services:
            try:
                subprocess.run("lxpanelctl restart", shell=True, check=True)
                subprocess.run(f"pkill -u {os.getlogin()} lxsession", shell=True, check=True)
                subprocess.run("lxsession &", shell=True, check=True)
                click.echo("Restarted LXDE session.")
            except subprocess.CalledProcessError as e:
                click.echo(f"Error restarting services: {e}")
        click.echo("Restore completed successfully.")
        return True
    except Exception as e:
        click.echo(f"Error during restore: {str(e)}")
        return False

def list_backups():
    """List available backup directories in the script's backup directory."""
    backup_dir = Path(__file__).parent / "backups"
    if not backup_dir.exists():
        return []
    return [str(f) for f in backup_dir.glob("lxde_backup_*") if f.is_dir()]

@click.group()
def cli():
    """AppImage Launcher CLI"""
    pass

@cli.command()
def menu():
    """Show interactive configuration menu"""
    show_menu()

def show_menu():
    """Show interactive configuration menu"""
    config = load_config()

    while True:
        click.clear()
        click.echo("AppImage Launcher Configuration")
        click.echo(f"1. Toggle Kiosk Mode: {'Enabled' if config['kiosk_mode'] else 'Disabled'}")
        click.echo(f"2. Silent Mode: {'Enabled' if config['silent_mode'] else 'Disabled'}")
        click.echo(f"3. Hide Mouse: {'Enabled' if config['hide_mouse'] else 'Disabled'}")
        click.echo(f"4. Checksum Verification: {'Enabled' if config['checksum_verification'] else 'Disabled'}")
        click.echo(f"5. Services:")
        for service, enabled in config["services"].items():
            click.echo(f"   - {service.capitalize()}: {'Enabled' if enabled else 'Disabled'}")
        click.echo(f"6. Test Current Checksum")
        click.echo(f"7. Update AppImage Checksum (Current: {config['appimage_md5'] or 'Not set'})")
        click.echo(f"8. Apply and Save Configuration (Persists after reboot with systemd service)")
        click.echo("9. Launch App Now")
        click.echo("10. Setup Kiosk Mode Immediately")
        click.echo("11. Setup Kiosk Mode and Launch App")
        click.echo(f"12. Manage Backups (Current: {config.get('backup_file', 'Not set')})")
        click.echo("13. Create LXDE Backup")
        click.echo("14. Restore LXDE Backup (No Restart)")
        click.echo("15. Exit")

        try:
            choice = click.prompt("Select an option (1-15)", type=int)
        except (ValueError, click.Abort):
            click.echo("Invalid input. Please enter a number between 1 and 15.")
            click.pause()
            continue

        if choice == 1:
            config["kiosk_mode"] = not config["kiosk_mode"]
            save_config(config)
            click.echo(f"Kiosk Mode is now {'Enabled' if config['kiosk_mode'] else 'Disabled'}.")
        elif choice == 2:
            config["silent_mode"] = not config["silent_mode"]
            save_config(config)
        elif choice == 3:
            config["hide_mouse"] = not config["hide_mouse"]
            save_config(config)
        elif choice == 4:
            config["checksum_verification"] = not config["checksum_verification"]
            save_config(config)
            click.echo(f"Checksum Verification is now {'Enabled' if config['checksum_verification'] else 'Disabled'}.")
        elif choice == 5:
            service_menu(config)
        elif choice == 6:
            if not config["appimage_md5"]:
                click.echo("No checksum stored. Use option 7 to generate and save a checksum first.")
            else:
                click.echo("Testing current checksum...")
                if verify_appimage(APPIMAGE_PATH, config["appimage_md5"]):
                    click.echo("✓ Checksum verification PASSED - AppImage is valid!")
                else:
                    click.echo("✗ Checksum verification FAILED - AppImage may be corrupted or modified!")
            click.pause()
        elif choice == 7:
            new_md5 = compute_md5(APPIMAGE_PATH)
            if new_md5:
                config["appimage_md5"] = new_md5
                save_config(config)
                click.echo(f"Updated AppImage MD5 checksum to: {new_md5}")
            else:
                click.echo(f"Error: AppImage '{APPIMAGE_PATH}' not found.")
            click.pause()
        elif choice == 8:
            apply_system_config(config)
            click.echo("Configuration applied and saved. Systemd service updated. Will persist after reboot.")
            click.pause()
        elif choice == 9:
            click.echo("Preparing to launch AppImage...")
            if config["checksum_verification"] and not verify_appimage(APPIMAGE_PATH, config["appimage_md5"]):
                click.echo("Aborting launch due to checksum failure.")
                click.pause()
                continue
            if config["kiosk_mode"]:
                manage_services(config)
                if config["hide_mouse"]:
                    hide_mouse()
            execute_pre_launch(config)
            launch_appimage(APPIMAGE_PATH, config["kiosk_mode"])
            break
        elif choice == 10:
            setup_kiosk_mode_immediately(config)
        elif choice == 11:
            setup_kiosk_mode_and_launch(config)
        elif choice == 12:
            backup_menu(config)
        elif choice == 13:
            backup_file = create_backup()
            if backup_file:
                config["backup_file"] = backup_file
                save_config(config)
                click.echo(f"Backup created and selected: {backup_file}")
                click.echo("Verifying backup contents...")
                try:
                    for config_path in get_config_paths():
                        backup_config_path = Path(backup_file) / config_path.relative_to(Path.home())
                        if backup_config_path.exists():
                            click.echo(f"  - {backup_config_path}")
                            for item in backup_config_path.rglob("*"):
                                click.echo(f"    - {item}")
                except Exception as e:
                    click.echo(f"Error verifying backup: {str(e)}")
            click.pause()
        elif choice == 14:
            if config.get("backup_file"):
                click.echo(f"Restoring from: {config['backup_file']}")
                if restore_backup(config["backup_file"], restart_services=True):
                    click.echo("Desktop configuration restored. Changes should be visible immediately.")
                else:
                    click.echo("Restore failed. Check the backup directory or try rebooting.")
            else:
                click.echo("No backup directory selected. Use option 12 to select a backup.")
            click.pause()
        elif choice == 15:
            click.echo("Exiting...")
            break
        else:
            click.echo("Invalid option. Please enter a number between 1 and 15.")
        click.pause()

def service_menu(config):
    services = list(config["services"].keys())

    while True:
        click.clear()
        click.echo("Service Configuration")
        for i, service in enumerate(services, 1):
            click.echo(f"{i}. {service.capitalize()}: {'Enabled' if config['services'][service] else 'Disabled'}")
        click.echo(f"{len(services) + 1}. Back")

        try:
            choice = click.prompt(f"Select a service (1-{len(services) + 1})", type=int)
        except (ValueError, click.Abort):
            click.echo(f"Invalid input. Please enter a number between 1 and {len(services) + 1}.")
            click.pause()
            continue

        if 1 <= choice <= len(services):
            service = services[choice - 1]
            config["services"][service] = not config["services"][service]
            save_config(config)
        elif choice == len(services) + 1:
            break
        else:
            click.echo(f"Invalid option. Please enter a number between 1 and {len(services) + 1}.")
        click.pause()

def backup_menu(config):
    """Menu to manage and select backup directories."""
    while True:
        click.clear()
        click.echo("Backup Management")
        backups = list_backups()
        if not backups:
            click.echo("No backups found.")
        else:
            for i, backup in enumerate(backups, 1):
                click.echo(f"{i}. {backup}")
        click.echo(f"{len(backups) + 1}. Create New Backup")
        click.echo(f"{len(backups) + 2}. Back")

        try:
            choice = click.prompt(f"Select an option (1-{len(backups) + 2})", type=int)
        except (ValueError, click.Abort):
            click.echo(f"Invalid input. Please enter a number between 1 and {len(backups) + 2}.")
            click.pause()
            continue

        if 1 <= choice <= len(backups):
            config["backup_file"] = backups[choice - 1]
            save_config(config)
            click.echo(f"Selected backup: {config['backup_file']}")
        elif choice == len(backups) + 1:
            backup_file = create_backup()
            if backup_file:
                config["backup_file"] = backup_file
                save_config(config)
                click.echo(f"New backup created and selected: {backup_file}")
        elif choice == len(backups) + 2:
            break
        else:
            click.echo(f"Invalid option. Please enter a number between 1 and {len(backups) + 2}.")
        click.pause()

def setup_kiosk_mode_immediately(config):
    """Set up kiosk mode immediately, requiring at least one existing backup."""
    backups = list_backups()
    if not backups:
        click.echo("Error: No backups exist. Create a backup using option 13 first.")
        click.pause()
        return

    click.echo("Setting up kiosk mode immediately...")
    backup_file = create_backup()
    if backup_file:
        config["backup_file"] = backup_file
        save_config(config)
        click.echo(f"Backup created before kiosk mode setup: {backup_file}")
    else:
        click.echo("Warning: Backup creation failed. Proceeding with kiosk mode setup.")

    config["kiosk_mode"] = True
    save_config(config)

    try:
        manage_services(config, persistent=True)
        if config["hide_mouse"]:
            try:
                subprocess.run("echo 'unclutter -idle 0 &' >> ~/.config/lxsession/LXDE-pi/autostart", shell=True, check=True)
                click.echo("Configured mouse hiding to persist on reboot.")
                hide_mouse()
            except subprocess.CalledProcessError as e:
                click.echo(f"Error configuring mouse hiding: {e}")
        panel_dir = os.path.expanduser("~/.config/lxpanel/LXDE-pi/panels")
        panel_file = os.path.join(panel_dir, "panel")
        try:
            os.makedirs(panel_dir, exist_ok=True)
            if not os.path.exists(panel_file):
                default_panel = "/etc/xdg/lxpanel/LXDE-pi/panels/panel"
                if os.path.exists(default_panel):
                    subprocess.run(f"cp {default_panel} {panel_file}", shell=True, check=True)
                else:
                    with open(panel_file, "w") as f:
                        f.write('{"global": {"autostart": true}}')
            subprocess.run("sudo sed -i 's/autostart=1/autostart=0/' " + panel_file, shell=True, check=True)
            with open(panel_file, "w") as f:
                subprocess.run("sudo sh -c 'echo \"{\\\"global\\\": {\\\"autostart\\\": false}}\" > " + panel_file + "'", shell=True, check=True)
            click.echo("Disabled LXDE panel and menus for kiosk mode.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error disabling GUI elements: {e}")
        try:
            with open(TEMPLATE_PATH, 'r') as f:
                service_template = f.read()
            service_content = service_template.format(
                TIMESTAMP=datetime.now().strftime("%I:%M %p EEST on %A, %B %d, %Y"),
                EXEC_PATH=os.path.abspath('launcher_cli.py'),
                USER=os.getlogin()
            )
            with open(SERVICE_FILE, 'w') as f:
                f.write(service_content)
            subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
            subprocess.run(["sudo", "systemctl", "enable", "launcher.service"], check=True)
            subprocess.run(["sudo", "systemctl", "start", "launcher.service"], check=True)
            click.echo("Systemd service enabled and started for kiosk mode.")
        except FileNotFoundError:
            click.echo(f"Error: Template file {TEMPLATE_PATH} not found.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error updating systemd service: {e}")
        click.echo("Kiosk mode setup completed. Log out or reboot to see changes.")
    except Exception as e:
        click.echo(f"Error setting up kiosk mode: {str(e)}")
    click.pause()

def setup_kiosk_mode_and_launch(config):
    """Set up kiosk mode and launch the AppImage immediately, requiring at least one existing backup."""
    backups = list_backups()
    if not backups:
        click.echo("Error: No backups exist. Create a backup using option 13 first.")
        click.pause()
        return

    click.echo("Setting up kiosk mode and launching AppImage...")
    backup_file = create_backup()
    if backup_file:
        config["backup_file"] = backup_file
        save_config(config)
        click.echo(f"Backup created before kiosk mode setup: {backup_file}")
    else:
        click.echo("Warning: Backup creation failed. Proceeding with kiosk mode setup.")

    config["kiosk_mode"] = True
    save_config(config)

    try:
        manage_services(config, persistent=True)
        if config["hide_mouse"]:
            try:
                subprocess.run("echo 'unclutter -idle 0 &' >> ~/.config/lxsession/LXDE-pi/autostart", shell=True, check=True)
                click.echo("Configured mouse hiding to persist on reboot.")
                hide_mouse()
            except subprocess.CalledProcessError as e:
                click.echo(f"Error configuring mouse hiding: {e}")
        panel_dir = os.path.expanduser("~/.config/lxpanel/LXDE-pi/panels")
        panel_file = os.path.join(panel_dir, "panel")
        try:
            os.makedirs(panel_dir, exist_ok=True)
            if not os.path.exists(panel_file):
                default_panel = "/etc/xdg/lxpanel/LXDE-pi/panels/panel"
                if os.path.exists(default_panel):
                    subprocess.run(f"cp {default_panel} {panel_file}", shell=True, check=True)
                else:
                    with open(panel_file, "w") as f:
                        f.write('{"global": {"autostart": true}}')
            subprocess.run("sudo sed -i 's/autostart=1/autostart=0/' " + panel_file, shell=True, check=True)
            with open(panel_file, "w") as f:
                subprocess.run("sudo sh -c 'echo \"{\\\"global\\\": {\\\"autostart\\\": false}}\" > " + panel_file + "'", shell=True, check=True)
            click.echo("Disabled LXDE panel and menus for kiosk mode.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error disabling GUI elements: {e}")
        try:
            with open(TEMPLATE_PATH, 'r') as f:
                service_template = f.read()
            service_content = service_template.format(
                TIMESTAMP=datetime.now().strftime("%I:%M %p EEST on %A, %B %d, %Y"),
                EXEC_PATH=os.path.abspath('launcher_cli.py'),
                USER=os.getlogin()
            )
            with open(SERVICE_FILE, 'w') as f:
                f.write(service_content)
            subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
            subprocess.run(["sudo", "systemctl", "enable", "launcher.service"], check=True)
            subprocess.run(["sudo", "systemctl", "start", "launcher.service"], check=True)
            click.echo("Systemd service enabled and started for kiosk mode.")
        except FileNotFoundError:
            click.echo(f"Error: Template file {TEMPLATE_PATH} not found.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error updating systemd service: {e}")
        if config["checksum_verification"] and not verify_appimage(APPIMAGE_PATH, config["appimage_md5"]):
            click.echo("Aborting launch due to checksum failure.")
            click.pause()
            return
        execute_pre_launch(config)
        launch_appimage(APPIMAGE_PATH, config["kiosk_mode"])
    except Exception as e:
        click.echo(f"Error setting up kiosk mode or launching AppImage: {str(e)}")
        click.pause()

def apply_system_config(config):
    """Apply system-wide configuration to persist after reboot and update systemd service from template."""
    current_time = datetime.now().strftime("%I:%M %p EEST on %A, %B %d, %Y")

    if config["kiosk_mode"]:
        backup_file = create_backup()
        if backup_file:
            config["backup_file"] = backup_file
            save_config(config)
            click.echo(f"Backup created before enabling kiosk mode: {backup_file}")
        else:
            click.echo("Warning: Backup creation failed. Proceeding with kiosk mode configuration.")

        manage_services(config, persistent=True)
        if config["hide_mouse"]:
            try:
                subprocess.run("echo 'unclutter -idle 0 &' >> ~/.config/lxsession/LXDE-pi/autostart", shell=True, check=True)
                click.echo("Configured mouse hiding to persist on reboot.")
            except subprocess.CalledProcessError as e:
                click.echo(f"Error configuring mouse hiding: {e}")
        panel_dir = os.path.expanduser("~/.config/lxpanel/LXDE-pi/panels")
        panel_file = os.path.join(panel_dir, "panel")
        try:
            os.makedirs(panel_dir, exist_ok=True)
            if not os.path.exists(panel_file):
                default_panel = "/etc/xdg/lxpanel/LXDE-pi/panels/panel"
                if os.path.exists(default_panel):
                    subprocess.run(f"cp {default_panel} {panel_file}", shell=True, check=True)
                else:
                    with open(panel_file, "w") as f:
                        f.write('{"global": {"autostart": true}}')
            subprocess.run("sudo sed -i 's/autostart=1/autostart=0/' " + panel_file, shell=True, check=True)
            with open(panel_file, "w") as f:
                subprocess.run("sudo sh -c 'echo \"{\\\"global\\\": {\\\"autostart\\\": false}}\" > " + panel_file + "'", shell=True, check=True)
            click.echo("Disabled LXDE panel and menus for kiosk mode.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error disabling GUI elements: {e}")
    else:
        if config.get("backup_file"):
            if restore_backup(config["backup_file"], restart_services=True):
                click.echo(f"Restored LXDE configuration from: {config['backup_file']}")
            else:
                click.echo(f"Warning: Failed to restore backup from {config['backup_file']}. Desktop may not be fully restored.")
        else:
            click.echo("Warning: No backup directory selected. Skipping configuration restore.")

        manage_services(config, persistent=True)
        autostart_file = os.path.expanduser("~/.config/lxsession/LXDE-pi/autostart")
        try:
            if os.path.exists(autostart_file):
                subprocess.run("sed -i '/unclutter/d' " + autostart_file, shell=True, check=True)
                click.echo("Removed mouse hiding from autostart.")
            else:
                click.echo("Autostart file not found, skipping mouse hiding removal.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error removing mouse hiding: {e}")
        try:
            panel_dir = os.path.expanduser("~/.config/lxpanel/LXDE-pi/panels")
            panel_file = os.path.join(panel_dir, "panel")
            if os.path.exists(panel_file):
                subprocess.run("sudo rm -f " + panel_file, shell=True, check=True)
                click.echo("Removed custom panel configuration.")
            lxde_config_dir = os.path.expanduser("~/.config/lxsession/LXDE-pi")
            if os.path.exists(lxde_config_dir):
                subprocess.run("sudo rm -f " + os.path.join(lxde_config_dir, "desktop.conf"), shell=True, check=True)
                click.echo("Removed custom desktop session configuration.")
            default_panel_dir = "/etc/xdg/lxpanel/LXDE-pi/panels"
            default_panel = os.path.join(default_panel_dir, "panel")
            if os.path.exists(default_panel):
                subprocess.run("sudo systemctl enable lxpanel", shell=True, check=True)
                subprocess.run("sudo systemctl enable lxsession", shell=True, check=True)
                click.echo("Re-enabled LXDE panel and session services.")
            subprocess.run("sudo systemctl restart lxpanel", shell=True, check=True)
            subprocess.run("sudo systemctl restart lxsession", shell=True, check=True)
            subprocess.run("sudo systemctl restart lightdm", shell=True, check=True)
            click.echo("Restarted LXDE services to restore desktop environment.")
            subprocess.run("sudo systemctl restart display-manager", shell=True, check=True)
            click.echo("Restarted display manager to ensure desktop restoration.")
        except subprocess.CalledProcessError as e:
            click.echo(f"Error re-enabling GUI elements: {e}")
            click.echo("Trying alternative restoration method...")
            try:
                subprocess.run("sudo systemctl restart lightdm", shell=True, check=True)
                click.echo("Restarted LightDM display manager.")
            except subprocess.CalledProcessError as e2:
                click.echo(f"Alternative restoration also failed: {e2}")
                click.echo("You may need to manually restart the system to restore the desktop.")

    try:
        with open(TEMPLATE_PATH, 'r') as f:
            service_template = f.read()
        service_content = service_template.format(
            TIMESTAMP=datetime.now().strftime("%I:%M %p EEST on %A, %B %d, %Y"),
            EXEC_PATH=os.path.abspath('launcher_cli.py'),
            USER=os.getlogin()
        )
        with open(SERVICE_FILE, 'w') as f:
            f.write(service_content)
        subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
        if config["kiosk_mode"]:
            subprocess.run(["sudo", "systemctl", "enable", "launcher.service"], check=True)
            subprocess.run(["sudo", "systemctl", "start", "launcher.service"], check=True)
            click.echo("Systemd service enabled and started for kiosk mode.")
        else:
            subprocess.run(["sudo", "systemctl", "disable", "launcher.service"], check=True)
            subprocess.run(["sudo", "systemctl", "stop", "launcher.service"], check=True)
            click.echo("Systemd service disabled for non-kiosk mode.")
    except FileNotFoundError:
        click.echo(f"Error: Template file {TEMPLATE_PATH} not found.")
    except subprocess.CalledProcessError as e:
        click.echo(f"Error updating systemd service: {e}")

def silent_mode_check(config):
    """Check for Enter key press in silent mode to enter menu, else launch AppImage."""
    click.echo(f"Launching in {SILENT_MODE_TIMEOUT} seconds. Press 'Enter' to enter configuration menu.")
    start_time = time.time()
    while time.time() - start_time < SILENT_MODE_TIMEOUT:
        if keyboard.is_pressed("enter"):
            click.echo("Entering configuration menu...")
            show_menu()
            return
        time.sleep(0.1)
    if config["checksum_verification"] and not verify_appimage(APPIMAGE_PATH, config["appimage_md5"]):
        click.echo("Aborting launch due to checksum failure.")
        sys.exit(1)
    if config["kiosk_mode"]:
        manage_services(config)
        if config["hide_mouse"]:
            hide_mouse()
    execute_pre_launch(config)
    launch_appimage(APPIMAGE_PATH, config["kiosk_mode"])

def main():
    """Main entry point: show menu directly if not in silent mode, else check for Enter key."""
    config = load_config()
    if config["silent_mode"]:
        silent_mode_check(config)
    else:
        show_menu()

if __name__ == "__main__":
    main()