import subprocess
import sys
import shutil
import shlex
from typing import Optional, Union


class TerminalController:
    """
    Provides methods to manage terminal operations.
    """
    @staticmethod
    def find_terminal_emulator() -> Optional[str]:
        """
        Find a suitable terminal emulator executable.
        """
        linux_terminals = [
            'gnome-terminal',
            'x-terminal-emulator',
            'konsole',
            'xfce4-terminal',
            'lxterminal',
            'mate-terminal'
        ]

        for terminal in linux_terminals:
            terminal_path = shutil.which(terminal)
            if terminal_path:
                return terminal_path
        return None

    @staticmethod
    def is_supported_platform() -> bool:
        """
        Check if the current platform is supported.
        """
        return any(sys.platform.startswith(p) for p in ['win', 'darwin', 'linux'])

    @staticmethod
    def run(command: Union[str, list[str]]) -> None:
        """
        Run a command in the appropriate terminal based on the operating system.
        """
        if not TerminalController.is_supported_platform():
            print("Platform not supported")
            return

        # Ensure command is a string for the terminal emulators
        if isinstance(command, list):
            full_command = shlex.join(command)
        else:
            full_command = command

        if sys.platform.startswith('win'):
            # On Windows, 'start' is a shell builtin, so shell=True is needed.
            # We use /k to keep the terminal open.
            subprocess.Popen(['start', 'cmd', '/k', full_command], shell=True)
        elif sys.platform.startswith('darwin'):
            # AppleScript requires the command to be inside double quotes.
            # We escape double quotes in the command.
            escaped_command = full_command.replace('"', '\\"')
            script = f'''
                tell application "Terminal"
                    do script "{escaped_command}"
                end tell
            '''
            subprocess.Popen(['osascript', '-e', script])
        elif sys.platform.startswith('linux'):
            terminal_emulator = TerminalController.find_terminal_emulator()
            if terminal_emulator:
                # Wrap the command to keep the terminal open after execution
                wrapped_command = f"{full_command}; exec $SHELL"
                subprocess.Popen(
                    [terminal_emulator, '-e', f'bash -c {shlex.quote(wrapped_command)}'])
            else:
                print("No terminal emulator found.")
 