import platform
import subprocess
import winreg
import os


class AppControl:
    """Application control operations for Windows, Linux, and macOS"""
    
    def __init__(self):
        self.os_type = platform.system().lower()
    
    def install(self, app_name, source=None, version=None):
        """Install an application"""
        if 'windows' in self.os_type:
            cmd = f'winget install --id {app_name} --exact --accept-source-agreements --accept-package-agreements'
            if version:
                cmd += f' --version {version}'
        elif 'darwin' in self.os_type:
            cmd = f'brew install {app_name}'
        else:
            cmd = f'sudo apt install -y {app_name}'
        subprocess.run(cmd, shell=True)
    
    def uninstall(self, app_name, force=False):
        """Uninstall an application"""
        if 'windows' in self.os_type:
            cmd = f'winget uninstall {app_name}'
        elif 'darwin' in self.os_type:
            cmd = f'brew uninstall {app_name}'
        else:
            cmd = f'sudo apt remove -y {app_name}'
        subprocess.run(cmd, shell=True)
    
    def update(self, app_name, version=None):
        """Update an application"""
        if 'windows' in self.os_type:
            cmd = f'winget upgrade {app_name}'
        elif 'darwin' in self.os_type:
            cmd = f'brew upgrade {app_name}'
        else:
            cmd = f'sudo apt install --only-upgrade {app_name}'
        subprocess.run(cmd, shell=True)
    
    def list_installed(self, filter=None):
        """List installed applications"""
        if 'windows' in self.os_type:
            cmd = 'winget list'
        elif 'darwin' in self.os_type:
            cmd = 'brew list'
        else:
            cmd = 'apt list --installed'
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
        return result.stdout
    
    def open_app(self, app_name, args=None):
        """Open an application"""
        if 'windows' in self.os_type:
            cmd = f'start {app_name}'
            if args:
                cmd += f' {args}'
        elif 'darwin' in self.os_type:
            cmd = f'open -a {app_name}'
        else:
            cmd = app_name
        subprocess.Popen(cmd, shell=True)
    
    def force_close(self, app_name):
        """Force close an application"""
        if 'windows' in self.os_type:
            subprocess.run(f'taskkill /F /IM {app_name}.exe', shell=True)
        else:
            subprocess.run(f'pkill -9 {app_name}', shell=True)
    
    def set_default(self, app_name, file_type):
        """Set default application for file type"""
        if 'windows' in self.os_type:
            subprocess.run(f'assoc {file_type}={app_name}', shell=True)
    
    def schedule_autostart(self, app_name, schedule, args=None):
        """Schedule app auto-start"""
        if 'windows' in self.os_type:
            cmd = f'schtasks /create /tn "{app_name}" /tr "{app_name}" /sc {schedule}'
            subprocess.run(cmd, shell=True)
    
    def toggle_startup(self, app_name, enabled):
        """Enable/disable startup programs"""
        if 'windows' in self.os_type:
            key_path = r'Software\Microsoft\Windows\CurrentVersion\Run'
            try:
                key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_ALL_ACCESS)
                if enabled:
                    winreg.SetValueEx(key, app_name, 0, winreg.REG_SZ, app_name)
                else:
                    winreg.DeleteValue(key, app_name)
                winreg.CloseKey(key)
            except:
                pass
    
    def get_version(self, app_name):
        """Get app version"""
        if 'windows' in self.os_type:
            result = subprocess.run(f'winget show {app_name}', shell=True, capture_output=True, text=True)
        elif 'darwin' in self.os_type:
            result = subprocess.run(f'brew info {app_name}', shell=True, capture_output=True, text=True)
        else:
            result = subprocess.run(f'apt show {app_name}', shell=True, capture_output=True, text=True)
        return result.stdout
