from typing import List
import subprocess
import psutil
from typography import Typography
class Command(Typography):
    """
    A utility class for executing and managing shell commands.
    Automatically created via Agents and applies logging via Typography.
    """

    def __init__(self,capture_output: bool = True, text:bool = True, shell:bool = False , **kwargs):
        """
        Initializes the Command class with dynamic logging.
        
        Args:
            **kwargs: Additional keyword arguments to pass to the superclass.
        """
        super().__init__(**kwargs)
        self.capture_output = capture_output
        self.text = text
        self.shell = shell


    from typing import List

    def _sanitize_command(self, command: List[str]) -> List[str]:
        """
        Sanitizes command arguments by stripping unnecessary whitespace.
        Asserts that the command is a list of strings.
        """
        assert all(isinstance(arg, str) for arg in command), "All elements of the command must be strings"
        
        return [arg.strip() for arg in command]

    def _run_subprocess(self, command: List[str]) -> subprocess.CompletedProcess:
        """
        Runs a sanitized subprocess command and returns the result.
        """
        sanitized_command = self._sanitize_command(command)
        result =  subprocess.run(
            sanitized_command,
            capture_output=self.capture_output,
            text=self.text,
            shell=self.shell,
        )

        # Log the output and error if any
        if result.stdout:
            self.logger.debug(f"Command Output:\n{result.stdout}")
        if result.stderr:
            self.logger.error(f"Command Error:\n{result.stderr}")
        return result


    def kill_related_subprocesses(self, command: List[str]):
        """
        Kills subprocesses matching the given command.
        """
        sanitized_command = self._sanitize_command(command)
        for proc in psutil.process_iter(["pid", "cmdline"]):
            try:
                if proc.info["cmdline"] and sanitized_command == proc.info["cmdline"]:
                    proc.kill()
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                continue

    def run_command(self, command: List[str]) -> subprocess.CompletedProcess:
        """
        Runs a shell command.
        """
        return self._run_subprocess(command)

    def run_command_with_pipe(self, commands: List[List[str]]) -> subprocess.CompletedProcess:
        """
        Executes a series of piped commands.
        """
        previous_process = None
        for command in commands:
            sanitized_command = self._sanitize_command(command)
            if previous_process is None:
                previous_process = subprocess.Popen(
                    sanitized_command, stdout=subprocess.PIPE, text=self.text, shell=self.shell
                )
            else:
                previous_process = subprocess.Popen(
                    sanitized_command,
                    stdin=previous_process.stdout,
                    stdout=subprocess.PIPE,
                    text=self.text,
                    shell=self.shell,
                )
        return previous_process.communicate()

    def check_and_install_packages(self, packages: List[str]):
        """
        Ensures specified packages are installed.
        """
        for package in packages:
            self._run_subprocess(["sudo", "apt-get", "install", "-y", package])

   