"""Safe OS execution adapter with deterministic methods."""

import os
import shutil
import platform
import subprocess
import psutil
from pathlib import Path
from typing import Optional
from ..models.execution_result import ExecutionResult


class SafeOSExecutionAdapter:
    """Safe OS abstraction layer with path validation and dry-run support."""

    def __init__(self, allowed_paths: Optional[list[str]] = None):
        """Initialize adapter.
        
        Args:
            allowed_paths: List of allowed path prefixes (None = all paths allowed)
        """
        self.allowed_paths = [Path(p).resolve() for p in allowed_paths] if allowed_paths else None

    def _validate_path(self, path: str) -> tuple[bool, str, Path]:
        """Validate path is safe and within allowed directories.
        
        Args:
            path: Path to validate
            
        Returns:
            Tuple of (is_valid, error_message, resolved_path)
        """
        try:
            resolved = Path(path).resolve()
            
            # Check if path contains dangerous patterns
            path_str = str(resolved)
            if '..' in path or path_str.startswith('//'):
                return False, "Path contains dangerous patterns", resolved
            
            # Check against allowed paths if configured
            if self.allowed_paths:
                if not any(str(resolved).startswith(str(allowed)) for allowed in self.allowed_paths):
                    return False, f"Path not in allowed directories", resolved
            
            return True, "", resolved
            
        except Exception as e:
            return False, f"Invalid path: {str(e)}", Path()

    def rename_file(self, path: str, new_name: str, dry_run: bool = False) -> ExecutionResult:
        """Rename a file or directory.
        
        Args:
            path: Current file path
            new_name: New name for the file (just the name, not full path)
            dry_run: If True, only validate without executing
            
        Returns:
            ExecutionResult
        """
        # Validate source path
        valid, error, src_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid path: {error}",
                dry_run=dry_run
            )
        
        # Check source exists
        if not src_path.exists():
            return ExecutionResult(
                success=False,
                message=f"File does not exist: {src_path}",
                dry_run=dry_run
            )
        
        # Create destination path (same directory, new name)
        dst_path = src_path.parent / new_name
        
        # Validate destination path
        valid, error, dst_path = self._validate_path(str(dst_path))
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid destination: {error}",
                dry_run=dry_run
            )
        
        # Check destination doesn't already exist
        if dst_path.exists():
            return ExecutionResult(
                success=False,
                message=f"Destination already exists: {dst_path}",
                dry_run=dry_run
            )
        
        # Dry run - return success without executing
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would rename {src_path} to {dst_path}",
                data={"source": str(src_path), "destination": str(dst_path)},
                dry_run=True
            )
        
        # Execute rename
        try:
            src_path.rename(dst_path)
            return ExecutionResult(
                success=True,
                message=f"Renamed {src_path.name} to {new_name}",
                data={"source": str(src_path), "destination": str(dst_path)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Rename failed: {str(e)}",
                dry_run=False
            )

    def move_file(self, source: str, destination: str, dry_run: bool = True) -> ExecutionResult:
        """Move file from source to destination.
        
        Args:
            source: Source file path
            destination: Destination file path
            dry_run: If True, only validate without executing
            
        Returns:
            ExecutionResult
        """
        # Validate source
        valid, error, src_path = self._validate_path(source)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid source: {error}",
                dry_run=dry_run
            )
        
        # Validate destination
        valid, error, dst_path = self._validate_path(destination)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid destination: {error}",
                dry_run=dry_run
            )
        
        # Check source exists
        if not src_path.exists():
            return ExecutionResult(
                success=False,
                message=f"Source does not exist: {src_path}",
                dry_run=dry_run
            )
        
        # Check source is a file
        if not src_path.is_file():
            return ExecutionResult(
                success=False,
                message=f"Source is not a file: {src_path}",
                dry_run=dry_run
            )
        
        # Dry run - return success without executing
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would move {src_path} to {dst_path}",
                data={"source": str(src_path), "destination": str(dst_path)},
                dry_run=True
            )
        
        # Execute move
        try:
            src_path.rename(dst_path)
            return ExecutionResult(
                success=True,
                message=f"Moved {src_path.name} to {dst_path}",
                data={"source": str(src_path), "destination": str(dst_path)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Move failed: {str(e)}",
                dry_run=False
            )

    def delete_file(self, path: str, dry_run: bool = True) -> ExecutionResult:
        """Delete file at path.
        
        Args:
            path: File path to delete
            dry_run: If True, only validate without executing
            
        Returns:
            ExecutionResult
        """
        # Validate path
        valid, error, file_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid path: {error}",
                dry_run=dry_run
            )
        
        # Check file exists
        if not file_path.exists():
            return ExecutionResult(
                success=False,
                message=f"File does not exist: {file_path}",
                dry_run=dry_run
            )
        
        # Check is a file
        if not file_path.is_file():
            return ExecutionResult(
                success=False,
                message=f"Path is not a file: {file_path}",
                dry_run=dry_run
            )
        
        # Dry run - return success without executing
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would delete {file_path}",
                data={"path": str(file_path), "size": file_path.stat().st_size},
                dry_run=True
            )
        
        # Execute delete
        try:
            file_path.unlink()
            return ExecutionResult(
                success=True,
                message=f"Deleted {file_path}",
                data={"path": str(file_path)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Delete failed: {str(e)}",
                dry_run=False
            )

    def restart_system(self, delay: int = 0, dry_run: bool = True) -> ExecutionResult:
        """Restart the system.
        
        Args:
            delay: Delay in seconds before restart
            dry_run: If True, only validate without executing (default: True)
            
        Returns:
            ExecutionResult
        """
        system = platform.system()
        
        # Dry run - return success without executing
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would restart {system} system with {delay}s delay",
                data={"system": system, "delay": delay},
                dry_run=True
            )
        
        # Build command based on OS (but don't execute - too dangerous)
        # In production, this would require additional safety checks
        return ExecutionResult(
            success=False,
            message="System restart requires explicit confirmation and elevated privileges",
            data={"system": system, "delay": delay},
            dry_run=False,
            metadata={"requires_confirmation": True, "requires_elevation": True}
        )

    def get_file_info(self, path: str) -> ExecutionResult:
        """Get file information (safe read-only operation).
        
        Args:
            path: File path
            
        Returns:
            ExecutionResult with file info
        """
        valid, error, file_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid path: {error}",
                dry_run=False
            )
        
        if not file_path.exists():
            return ExecutionResult(
                success=False,
                message=f"Path does not exist: {file_path}",
                dry_run=False
            )
        
        try:
            stat = file_path.stat()
            return ExecutionResult(
                success=True,
                message=f"File info for {file_path}",
                data={
                    "path": str(file_path),
                    "size": stat.st_size,
                    "is_file": file_path.is_file(),
                    "is_dir": file_path.is_dir(),
                    "exists": True
                },
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Failed to get file info: {str(e)}",
                dry_run=False
            )

    def create_folder(self, name: str, path: str, parents: bool = True, dry_run: bool = True) -> ExecutionResult:
        """Create a new folder.
        
        Args:
            name: Folder name
            path: Parent directory path
            parents: Create parent directories if needed
            dry_run: If True, only validate without executing
            
        Returns:
            ExecutionResult
        """
        # Validate parent path
        valid, error, parent_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid parent path: {error}",
                dry_run=dry_run
            )
        
        # Create full folder path
        folder_path = parent_path / name
        
        # Check if already exists
        if folder_path.exists():
            return ExecutionResult(
                success=False,
                message=f"Folder already exists: {folder_path}",
                dry_run=dry_run
            )
        
        # Dry run
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would create folder {folder_path}",
                data={"path": str(folder_path), "parents": parents},
                dry_run=True
            )
        
        # Execute
        try:
            folder_path.mkdir(parents=parents, exist_ok=False)
            return ExecutionResult(
                success=True,
                message=f"Created folder {folder_path}",
                data={"path": str(folder_path)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Failed to create folder: {str(e)}",
                dry_run=False
            )

    def read_file(self, path: str, encoding: str = "utf-8") -> ExecutionResult:
        """Read file contents.
        
        Args:
            path: File path
            encoding: File encoding
            
        Returns:
            ExecutionResult with file contents
        """
        valid, error, file_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid path: {error}",
                dry_run=False
            )
        
        if not file_path.exists():
            return ExecutionResult(
                success=False,
                message=f"File does not exist: {file_path}",
                dry_run=False
            )
        
        if not file_path.is_file():
            return ExecutionResult(
                success=False,
                message=f"Path is not a file: {file_path}",
                dry_run=False
            )
        
        try:
            content = file_path.read_text(encoding=encoding)
            return ExecutionResult(
                success=True,
                message=f"Read {len(content)} characters from {file_path}",
                data={"path": str(file_path), "content": content, "size": len(content)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Failed to read file: {str(e)}",
                dry_run=False
            )

    def create_file(self, path: str, content: str = "", dry_run: bool = True) -> ExecutionResult:
        """Create a new file."""
        valid, error, file_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(success=False, message=f"Invalid path: {error}", dry_run=dry_run)
        
        if file_path.exists():
            return ExecutionResult(success=False, message=f"File already exists: {file_path}", dry_run=dry_run)
        
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would create file {file_path}", dry_run=True)
        
        try:
            file_path.parent.mkdir(parents=True, exist_ok=True)
            file_path.write_text(content, encoding="utf-8")
            return ExecutionResult(success=True, message=f"Created file {file_path}", data={"path": str(file_path)}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Failed: {str(e)}", dry_run=False)
        """Write content to file.
        
        Args:
            path: File path
            content: Content to write
            mode: Write mode ('w' or 'a')
            encoding: File encoding
            dry_run: If True, only validate without executing
            
        Returns:
            ExecutionResult
        """
        valid, error, file_path = self._validate_path(path)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid path: {error}",
                dry_run=dry_run
            )
        
        # Dry run
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would write {len(content)} characters to {file_path}",
                data={"path": str(file_path), "size": len(content), "mode": mode},
                dry_run=True
            )
        
        # Execute
        try:
            file_path.write_text(content, encoding=encoding)
            return ExecutionResult(
                success=True,
                message=f"Wrote {len(content)} characters to {file_path}",
                data={"path": str(file_path), "size": len(content)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Failed to write file: {str(e)}",
                dry_run=False
            )

    def copy_file(self, source: str, destination: str, overwrite: bool = False, dry_run: bool = True) -> ExecutionResult:
        """Copy file from source to destination.
        
        Args:
            source: Source file path
            destination: Destination file path
            overwrite: Allow overwriting existing file
            dry_run: If True, only validate without executing
            
        Returns:
            ExecutionResult
        """
        # Validate source
        valid, error, src_path = self._validate_path(source)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid source: {error}",
                dry_run=dry_run
            )
        
        # Validate destination
        valid, error, dst_path = self._validate_path(destination)
        if not valid:
            return ExecutionResult(
                success=False,
                message=f"Invalid destination: {error}",
                dry_run=dry_run
            )
        
        # Check source exists
        if not src_path.exists():
            return ExecutionResult(
                success=False,
                message=f"Source does not exist: {src_path}",
                dry_run=dry_run
            )
        
        # Check source is file
        if not src_path.is_file():
            return ExecutionResult(
                success=False,
                message=f"Source is not a file: {src_path}",
                dry_run=dry_run
            )
        
        # Check destination doesn't exist (unless overwrite)
        if dst_path.exists() and not overwrite:
            return ExecutionResult(
                success=False,
                message=f"Destination already exists: {dst_path}",
                dry_run=dry_run
            )
        
        # Dry run
        if dry_run:
            return ExecutionResult(
                success=True,
                message=f"[DRY RUN] Would copy {src_path} to {dst_path}",
                data={"source": str(src_path), "destination": str(dst_path)},
                dry_run=True
            )
        
        # Execute
        try:
            shutil.copy2(str(src_path), str(dst_path))
            return ExecutionResult(
                success=True,
                message=f"Copied {src_path} to {dst_path}",
                data={"source": str(src_path), "destination": str(dst_path)},
                dry_run=False
            )
        except Exception as e:
            return ExecutionResult(
                success=False,
                message=f"Copy failed: {str(e)}",
                dry_run=False
            )

    def shutdown_system(self, delay: int = 0, force: bool = False, dry_run: bool = True) -> ExecutionResult:
        """Shutdown the system."""
        system = platform.system()
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would shutdown {system} with {delay}s delay", data={"system": system, "delay": delay}, dry_run=True)
        try:
            if 'windows' in system.lower():
                cmd = f'shutdown /s /t {delay}'
                if force:
                    cmd += ' /f'
            elif 'darwin' in system.lower():
                cmd = f'sudo shutdown -h +{delay//60}'
            else:
                cmd = f'sudo shutdown -h +{delay//60}'
            subprocess.run(cmd, shell=True, check=True)
            return ExecutionResult(success=True, message=f"System shutting down in {delay}s", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Shutdown failed: {str(e)}", dry_run=False)

    def sleep_system(self, dry_run: bool = True) -> ExecutionResult:
        """Put system to sleep."""
        if dry_run:
            return ExecutionResult(success=True, message="[DRY RUN] Would put system to sleep", dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run('rundll32.exe powrprof.dll,SetSuspendState 0,1,0', shell=True)
            elif 'darwin' in system:
                subprocess.run('pmset sleepnow', shell=True)
            else:
                subprocess.run('systemctl suspend', shell=True)
            return ExecutionResult(success=True, message="System going to sleep", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Sleep failed: {str(e)}", dry_run=False)

    def hibernate_system(self, dry_run: bool = True) -> ExecutionResult:
        """Hibernate the system."""
        if dry_run:
            return ExecutionResult(success=True, message="[DRY RUN] Would hibernate system", dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run('shutdown /h', shell=True)
            elif 'darwin' in system:
                subprocess.run('pmset hibernatemode 25 && pmset sleepnow', shell=True)
            else:
                subprocess.run('systemctl hibernate', shell=True)
            return ExecutionResult(success=True, message="System hibernating", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Hibernate failed: {str(e)}", dry_run=False)

    def lock_screen(self, dry_run: bool = True) -> ExecutionResult:
        """Lock the screen."""
        if dry_run:
            return ExecutionResult(success=True, message="[DRY RUN] Would lock screen", dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run('rundll32.exe user32.dll,LockWorkStation', shell=True)
            elif 'darwin' in system:
                subprocess.run('/System/Library/CoreServices/Menu\\ Extras/User.menu/Contents/Resources/CGSession -suspend', shell=True)
            else:
                subprocess.run('loginctl lock-session', shell=True)
            return ExecutionResult(success=True, message="Screen locked", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Lock failed: {str(e)}", dry_run=False)

    def get_system_resources(self) -> ExecutionResult:
        """Get CPU and RAM usage."""
        try:
            data = {
                'cpu_percent': psutil.cpu_percent(interval=1),
                'cpu_count': psutil.cpu_count(),
                'memory_percent': psutil.virtual_memory().percent,
                'memory_total': psutil.virtual_memory().total,
                'memory_available': psutil.virtual_memory().available,
                'memory_used': psutil.virtual_memory().used
            }
            return ExecutionResult(success=True, message="System resources retrieved", data=data, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Failed to get resources: {str(e)}", dry_run=False)

    def get_system_info(self) -> ExecutionResult:
        """Get system information."""
        try:
            data = {
                'system': platform.system(),
                'release': platform.release(),
                'version': platform.version(),
                'machine': platform.machine(),
                'processor': platform.processor(),
                'hostname': platform.node()
            }
            return ExecutionResult(success=True, message="System info retrieved", data=data, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Failed to get info: {str(e)}", dry_run=False)

    def kill_process(self, pid: int, force: bool = False, dry_run: bool = True) -> ExecutionResult:
        """Kill a process by PID."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would kill process {pid}", data={"pid": pid}, dry_run=True)
        try:
            proc = psutil.Process(pid)
            proc.kill() if force else proc.terminate()
            return ExecutionResult(success=True, message=f"Process {pid} terminated", data={"pid": pid}, dry_run=False)
        except psutil.NoSuchProcess:
            return ExecutionResult(success=False, message=f"Process {pid} not found", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Kill failed: {str(e)}", dry_run=False)

    def start_service(self, name: str, dry_run: bool = True) -> ExecutionResult:
        """Start a service."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would start service {name}", data={"name": name}, dry_run=True)
        return ExecutionResult(success=False, message="Service control requires explicit confirmation", dry_run=False, metadata={"requires_confirmation": True})

    def stop_service(self, name: str, dry_run: bool = True) -> ExecutionResult:
        """Stop a service."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would stop service {name}", data={"name": name}, dry_run=True)
        return ExecutionResult(success=False, message="Service control requires explicit confirmation", dry_run=False, metadata={"requires_confirmation": True})

    def enable_service(self, name: str, dry_run: bool = True) -> ExecutionResult:
        """Enable a service."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would enable service {name}", data={"name": name}, dry_run=True)
        return ExecutionResult(success=False, message="Service control requires explicit confirmation", dry_run=False, metadata={"requires_confirmation": True})

    def disable_service(self, name: str, dry_run: bool = True) -> ExecutionResult:
        """Disable a service."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would disable service {name}", data={"name": name}, dry_run=True)
        return ExecutionResult(success=False, message="Service control requires explicit confirmation", dry_run=False, metadata={"requires_confirmation": True})

    def change_system_setting(self, setting: str, value: str, dry_run: bool = True) -> ExecutionResult:
        """Change system settings."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would change {setting} to {value}", data={"setting": setting, "value": value}, dry_run=True)
        
        system = platform.system().lower()
        setting_lower = setting.lower()
        
        # Volume control
        if 'volume' in setting_lower or 'sound' in setting_lower or 'audio' in setting_lower:
            try:
                # Use PowerShell for simple mute toggle
                subprocess.run('powershell -Command "(New-Object -ComObject WScript.Shell).SendKeys([char]173)"', shell=True, check=True)
                return ExecutionResult(success=True, message="Volume toggled (mute/unmute)", dry_run=False)
            except Exception as e:
                return ExecutionResult(success=False, message=f"Volume control failed: {str(e)}", dry_run=False)
        
        # Network control - user mode alternative
        if 'network' in setting_lower or 'internet' in setting_lower or 'wifi' in setting_lower:
            return ExecutionResult(
                success=False, 
                message="Network control requires administrator privileges. Please run as admin or use Windows Settings > Network & Internet to disable manually.",
                dry_run=False,
                metadata={"requires_admin": True, "manual_steps": "Windows Settings > Network & Internet > Change adapter options > Right-click adapter > Disable"}
            )
        
        return ExecutionResult(success=False, message=f"Setting '{setting}' not supported in user mode", dry_run=False)

    def control_volume(self, action: str, level: int = None, dry_run: bool = False) -> ExecutionResult:
        """Control system volume.
        
        Args:
            action: 'mute', 'unmute', or 'set'
            level: Volume level 0-100 (for 'set' action)
            dry_run: If True, only validate without executing
        """
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would {action} volume", dry_run=True)
        
        try:
            subprocess.run('powershell -Command "(New-Object -ComObject WScript.Shell).SendKeys([char]173)"', shell=True, check=True)
            return ExecutionResult(success=True, message=f"Volume {action}d", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Volume control failed: {str(e)}", dry_run=False)

    def update_os(self, auto_install: bool = False, dry_run: bool = True) -> ExecutionResult:
        """Update the operating system."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would update OS (auto_install={auto_install})", data={"auto_install": auto_install}, dry_run=True)
        return ExecutionResult(success=False, message="OS update requires explicit confirmation", dry_run=False, metadata={"requires_confirmation": True})

    def open_browser(self, url: str, query: str = None, dry_run: bool = True) -> ExecutionResult:
        """Open URL in browser."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would open {url}", dry_run=True)
        try:
            import webbrowser
            if query:
                url = f"{url}/search?q={query.replace(' ', '+')}"
            webbrowser.open(url)
            return ExecutionResult(success=True, message=f"Opened {url}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Failed: {str(e)}", dry_run=False)

    def install_app(self, app_name: str, source: str = None, version: str = None, dry_run: bool = True) -> ExecutionResult:
        """Install an application."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would install {app_name}", data={"app_name": app_name, "version": version}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                cmd = f'winget install {app_name} --silent --accept-source-agreements --accept-package-agreements'
                if version:
                    cmd += f' --version {version}'
                result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=180)
                if result.returncode == 0:
                    return ExecutionResult(success=True, message=f"Installed {app_name}", data={"output": result.stdout}, dry_run=False)
                else:
                    return ExecutionResult(success=False, message=f"Install failed: {result.stderr}", dry_run=False)
            elif 'darwin' in system:
                cmd = f'brew install {app_name}'
            else:
                cmd = f'sudo apt install -y {app_name}'
            subprocess.run(cmd, shell=True, check=True, timeout=180)
            return ExecutionResult(success=True, message=f"Installed {app_name}", dry_run=False)
        except subprocess.TimeoutExpired:
            return ExecutionResult(success=False, message=f"Install timed out after 3 minutes", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Install failed: {str(e)}", dry_run=False)

    def uninstall_app(self, app_name: str, force: bool = False, dry_run: bool = True) -> ExecutionResult:
        """Uninstall an application."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would uninstall {app_name}", data={"app_name": app_name}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run(f'winget uninstall {app_name}', shell=True, check=True)
            elif 'darwin' in system:
                subprocess.run(f'brew uninstall {app_name}', shell=True, check=True)
            else:
                subprocess.run(f'sudo apt remove -y {app_name}', shell=True, check=True)
            return ExecutionResult(success=True, message=f"Uninstalled {app_name}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Uninstall failed: {str(e)}", dry_run=False)

    def update_app(self, app_name: str, version: str = None, dry_run: bool = True) -> ExecutionResult:
        """Update an application."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would update {app_name}", data={"app_name": app_name}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run(f'winget upgrade {app_name}', shell=True, check=True)
            elif 'darwin' in system:
                subprocess.run(f'brew upgrade {app_name}', shell=True, check=True)
            else:
                subprocess.run(f'sudo apt install --only-upgrade {app_name}', shell=True, check=True)
            return ExecutionResult(success=True, message=f"Updated {app_name}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Update failed: {str(e)}", dry_run=False)

    def list_apps(self, filter: str = None) -> ExecutionResult:
        """List installed applications."""
        try:
            system = platform.system().lower()
            if 'windows' in system:
                result = subprocess.run('winget list', shell=True, capture_output=True, text=True)
            elif 'darwin' in system:
                result = subprocess.run('brew list', shell=True, capture_output=True, text=True)
            else:
                result = subprocess.run('apt list --installed', shell=True, capture_output=True, text=True)
            return ExecutionResult(success=True, message="Listed installed apps", data={"output": result.stdout}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"List failed: {str(e)}", dry_run=False)

    def open_app(self, app_name: str, args: str = None, dry_run: bool = True) -> ExecutionResult:
        """Open an application."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would open {app_name}", data={"app_name": app_name}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                import os
                
                app_lower = app_name.lower().replace(' ', '')
                
                # Known app paths (fast lookup)
                known_apps = {
                    'teams': r'%LocalAppData%\Microsoft\Teams\current\Teams.exe',
                    'postman': r'%LocalAppData%\Postman\Postman.exe',
                    'slack': r'%LocalAppData%\slack\slack.exe',
                    'discord': r'%LocalAppData%\Discord\app-*\Discord.exe',
                    'vscode': r'%LocalAppData%\Programs\Microsoft VS Code\Code.exe',
                    'chrome': r'%ProgramFiles%\Google\Chrome\Application\chrome.exe'
                }
                
                # Try known path first
                if app_lower in known_apps:
                    known_path = os.path.expandvars(known_apps[app_lower])
                    if '*' in known_path:
                        # Handle wildcard paths
                        import glob
                        matches = glob.glob(known_path)
                        if matches:
                            subprocess.Popen([matches[0]], shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                            return ExecutionResult(success=True, message=f"Opened {app_name}", dry_run=False)
                    elif os.path.exists(known_path):
                        subprocess.Popen([known_path], shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                        return ExecutionResult(success=True, message=f"Opened {app_name}", dry_run=False)
                
                # Search Start Menu shortcuts
                start_menu_paths = [
                    os.path.expandvars(r'%AppData%\Microsoft\Windows\Start Menu\Programs'),
                    os.path.expandvars(r'%ProgramData%\Microsoft\Windows\Start Menu\Programs')
                ]
                
                for start_path in start_menu_paths:
                    if os.path.exists(start_path):
                        for root, dirs, files in os.walk(start_path):
                            for file in files:
                                file_lower = file.lower().replace(' ', '')
                                if app_lower in file_lower and file.endswith('.lnk'):
                                    lnk_path = os.path.join(root, file)
                                    os.startfile(lnk_path)
                                    return ExecutionResult(success=True, message=f"Opened {app_name}", dry_run=False)
                
                # Search executables
                search_paths = [
                    os.path.expandvars(r'%LocalAppData%\Programs'),
                    os.path.expandvars(r'%LocalAppData%\Microsoft'),
                    os.path.expandvars(r'%AppData%\Local'),
                    os.path.expandvars(r'%ProgramFiles%'),
                    os.path.expandvars(r'%ProgramFiles(x86)%'),
                    os.path.expandvars(r'C:\Program Files\PostgreSQL')
                ]
                
                for base_path in search_paths:
                    if not os.path.exists(base_path):
                        continue
                    try:
                        for root, dirs, files in os.walk(base_path):
                            dirs[:] = [d for d in dirs if d not in ['Windows', 'WindowsApps', 'System32', 'Common Files', 'WinSxS']]
                            if root.count(os.sep) - base_path.count(os.sep) > 4:
                                del dirs[:]
                            
                            for file in files:
                                file_lower = file.lower().replace(' ', '')
                                if app_lower in file_lower and file.endswith('.exe'):
                                    exe_path = os.path.join(root, file)
                                    subprocess.Popen([exe_path], shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                                    return ExecutionResult(success=True, message=f"Opened {app_name}", dry_run=False)
                    except (PermissionError, OSError):
                        continue
                
                return ExecutionResult(success=False, message=f"Could not find {app_name}. Try the full app name.", dry_run=False)
            elif 'darwin' in system:
                subprocess.Popen(['open', '-a', app_name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            else:
                subprocess.Popen([app_name], shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            return ExecutionResult(success=True, message=f"Opened {app_name}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Open failed: {str(e)}", dry_run=False)

    def force_close_app(self, app_name: str, dry_run: bool = True) -> ExecutionResult:
        """Force close an application."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would force close {app_name}", data={"app_name": app_name}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run(f'taskkill /F /IM {app_name}.exe', shell=True, check=True)
            else:
                subprocess.run(f'pkill -9 {app_name}', shell=True, check=True)
            return ExecutionResult(success=True, message=f"Force closed {app_name}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Force close failed: {str(e)}", dry_run=False)

    def set_default_app(self, app_name: str, file_type: str, dry_run: bool = True) -> ExecutionResult:
        """Set default application for file type."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would set {app_name} as default for {file_type}", data={"app_name": app_name, "file_type": file_type}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run(f'assoc {file_type}={app_name}', shell=True, check=True)
            return ExecutionResult(success=True, message=f"Set {app_name} as default for {file_type}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Set default failed: {str(e)}", dry_run=False)

    def schedule_app_autostart(self, app_name: str, schedule: str, args: str = None, dry_run: bool = True) -> ExecutionResult:
        """Schedule app auto-start."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would schedule {app_name} to autostart at {schedule}", data={"app_name": app_name, "schedule": schedule}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                cmd = f'schtasks /create /tn "{app_name}" /tr "{app_name}" /sc {schedule}'
                subprocess.run(cmd, shell=True, check=True)
            return ExecutionResult(success=True, message=f"Scheduled {app_name} autostart", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Schedule failed: {str(e)}", dry_run=False)

    def toggle_app_startup(self, app_name: str, enabled: bool, dry_run: bool = True) -> ExecutionResult:
        """Enable/disable startup programs."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would {'enable' if enabled else 'disable'} {app_name} at startup", data={"app_name": app_name, "enabled": enabled}, dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                import winreg
                key_path = r'Software\Microsoft\Windows\CurrentVersion\Run'
                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)
            return ExecutionResult(success=True, message=f"{'Enabled' if enabled else 'Disabled'} {app_name} at startup", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Toggle startup failed: {str(e)}", dry_run=False)

    def get_app_version(self, app_name: str) -> ExecutionResult:
        """Get app version."""
        try:
            system = platform.system().lower()
            if 'windows' in system:
                result = subprocess.run(f'winget show {app_name}', shell=True, capture_output=True, text=True)
            elif 'darwin' in system:
                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 ExecutionResult(success=True, message=f"Version info for {app_name}", data={"output": result.stdout}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Get version failed: {str(e)}", dry_run=False)

    def monitor_cpu_threshold(self, threshold: float, duration: int = 60) -> ExecutionResult:
        """Monitor CPU threshold."""
        try:
            cpu = psutil.cpu_percent(interval=1)
            exceeded = cpu > threshold
            return ExecutionResult(success=True, message=f"CPU: {cpu}% (threshold: {threshold}%)", data={"cpu_percent": cpu, "threshold": threshold, "exceeded": exceeded}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Monitor failed: {str(e)}", dry_run=False)

    def monitor_ram_spike(self, spike_threshold: float) -> ExecutionResult:
        """Detect RAM spikes."""
        try:
            mem = psutil.virtual_memory()
            spike = mem.percent > spike_threshold
            return ExecutionResult(success=True, message=f"RAM: {mem.percent}% (spike threshold: {spike_threshold}%)", data={"ram_percent": mem.percent, "spike_threshold": spike_threshold, "spike_detected": spike}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Monitor failed: {str(e)}", dry_run=False)

    def monitor_crash_loop(self, service_name: str, restart_threshold: int = 3) -> ExecutionResult:
        """Detect crash loops."""
        try:
            for proc in psutil.process_iter(['name', 'create_time']):
                if service_name.lower() in proc.info['name'].lower():
                    return ExecutionResult(success=True, message=f"Service {service_name} running", data={"service": service_name, "status": "running"}, dry_run=False)
            return ExecutionResult(success=True, message=f"Service {service_name} not running", data={"service": service_name, "status": "stopped"}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Monitor failed: {str(e)}", dry_run=False)

    def monitor_error_logs(self, log_path: str) -> ExecutionResult:
        """Analyze error logs."""
        try:
            with open(log_path, 'r') as f:
                lines = f.readlines()[-100:]
                errors = [l for l in lines if 'error' in l.lower() or 'exception' in l.lower()]
            return ExecutionResult(success=True, message=f"Found {len(errors)} errors", data={"error_count": len(errors), "errors": errors[:10]}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Analysis failed: {str(e)}", dry_run=False)

    def monitor_root_cause(self, incident_id: str) -> ExecutionResult:
        """Identify root cause."""
        return ExecutionResult(success=True, message=f"Root cause analysis for {incident_id}", data={"incident_id": incident_id, "analysis": "Requires AI analysis"}, dry_run=False)

    def monitor_disk_full(self, threshold_percent: float, path: str = None) -> ExecutionResult:
        """Detect disk nearing full."""
        try:
            disk = psutil.disk_usage(path or '/')
            critical = disk.percent > threshold_percent
            return ExecutionResult(success=True, message=f"Disk: {disk.percent}% (threshold: {threshold_percent}%)", data={"disk_percent": disk.percent, "threshold": threshold_percent, "critical": critical}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Monitor failed: {str(e)}", dry_run=False)

    def monitor_predict_failure(self, service_name: str) -> ExecutionResult:
        """Predict service failure."""
        return ExecutionResult(success=True, message=f"Failure prediction for {service_name}", data={"service": service_name, "prediction": "Requires ML model"}, dry_run=False)

    def autofix_config_mismatch(self, config_path: str, expected_config: dict, dry_run: bool = True) -> ExecutionResult:
        """Auto-fix config mismatch."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would fix config at {config_path}", dry_run=True)
        try:
            import json
            with open(config_path, 'w') as f:
                json.dump(expected_config, f, indent=2)
            return ExecutionResult(success=True, message=f"Fixed config at {config_path}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Fix failed: {str(e)}", dry_run=False)

    def autofix_rollback_update(self, service_name: str, dry_run: bool = True) -> ExecutionResult:
        """Auto-rollback failed update."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would rollback {service_name}", dry_run=True)
        return ExecutionResult(success=False, message="Rollback requires checkpoint ID", dry_run=False, metadata={"requires_confirmation": True})

    def wifi_disconnect(self, interface: str = None, dry_run: bool = True) -> ExecutionResult:
        """Disconnect from WiFi."""
        if dry_run:
            return ExecutionResult(success=True, message="[DRY RUN] Would disconnect WiFi", dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run('netsh wlan disconnect', shell=True, check=True)
            elif 'darwin' in system:
                subprocess.run('networksetup -setairportpower en0 off', shell=True, check=True)
            else:
                subprocess.run('nmcli radio wifi off', shell=True, check=True)
            return ExecutionResult(success=True, message="WiFi disconnected", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Disconnect failed: {str(e)}", dry_run=False)

    def wifi_connect(self, ssid: str, password: str = None, dry_run: bool = True) -> ExecutionResult:
        """Connect to WiFi."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would connect to {ssid}", dry_run=True)
        try:
            system = platform.system().lower()
            if 'windows' in system:
                subprocess.run(f'netsh wlan connect name="{ssid}"', shell=True, check=True)
            elif 'darwin' in system:
                subprocess.run(f'networksetup -setairportnetwork en0 "{ssid}" {password or ""}', shell=True, check=True)
            else:
                subprocess.run(f'nmcli device wifi connect "{ssid}" password "{password or ""}"', shell=True, check=True)
            return ExecutionResult(success=True, message=f"Connected to {ssid}", dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Connect failed: {str(e)}", dry_run=False)

    def network_check_ip(self, interface: str = None) -> ExecutionResult:
        """Check IP address."""
        try:
            result = subprocess.run('ipconfig', shell=True, capture_output=True, text=True, timeout=10)
            return ExecutionResult(success=True, message="IP configuration retrieved", data={"output": result.stdout}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Failed: {str(e)}", dry_run=False)

    def network_ping(self, host: str, count: int = 4, dry_run: bool = False) -> ExecutionResult:
        """Ping a host."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would ping {host}", dry_run=True)
        try:
            result = subprocess.run(f'ping -n {count} {host}', shell=True, capture_output=True, text=True, timeout=30)
            return ExecutionResult(success=result.returncode == 0, message=f"Pinged {host}", data={"output": result.stdout}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Ping failed: {str(e)}", dry_run=False)

    def network_flush_dns(self, dry_run: bool = False) -> ExecutionResult:
        """Flush DNS cache."""
        if dry_run:
            return ExecutionResult(success=True, message="[DRY RUN] Would flush DNS", dry_run=True)
        try:
            result = subprocess.run('ipconfig /flushdns', shell=True, capture_output=True, text=True, timeout=10)
            return ExecutionResult(success=result.returncode == 0, message="DNS cache flushed", data={"output": result.stdout}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Failed: {str(e)}", dry_run=False)

    def setup_java(self, version: str, install_path: str = None, dry_run: bool = False) -> ExecutionResult:
        """Setup Java environment (JAVA_HOME and PATH)."""
        if dry_run:
            return ExecutionResult(success=True, message=f"[DRY RUN] Would setup Java {version} at {install_path}", dry_run=True)
        try:
            if not install_path:
                return ExecutionResult(success=False, message="install_path is required", dry_run=False)
            
            java_path = Path(install_path)
            if not java_path.exists():
                return ExecutionResult(success=False, message=f"Java installation not found at {install_path}", dry_run=False)
            
            # Set JAVA_HOME
            subprocess.run(f'setx JAVA_HOME "{install_path}"', shell=True, check=True)
            
            # Add to PATH
            bin_path = str(java_path / "bin")
            subprocess.run(f'setx PATH "%PATH%;{bin_path}"', shell=True, check=True)
            
            return ExecutionResult(success=True, message=f"Java {version} configured: JAVA_HOME={install_path}", data={"version": version, "java_home": install_path}, dry_run=False)
        except Exception as e:
            return ExecutionResult(success=False, message=f"Setup failed: {str(e)}", dry_run=False)
