from typing import Dict

from libs.osaf.common.exceptions import ScriptExecutionError


class ScriptEngine:
    """Script execution engine for SysPack"""

    def __init__(self, osaf_core):
        self.core = osaf_core
        self.log = osaf_core.log

    def execute_script(self, script_path: str, env_vars: Dict[str, str] = None) -> bool:
        """Execute a SysPack script"""
        try:
            if not self.core.files.exists(script_path):
                raise ScriptExecutionError(f"Script not found: {script_path}")

            # Determine script type
            if script_path.endswith('.py'):
                return self._execute_python_script(script_path, env_vars)
            elif script_path.endswith('.sh') or script_path.endswith('.bat'):
                return self._execute_shell_script(script_path, env_vars)
            else:
                raise ScriptExecutionError(f"Unsupported script type: {script_path}")

        except Exception as e:
            self.log.e(f"Script execution failed: {e}")
            return False

    def _execute_python_script(self, script_path: str, env_vars: Dict[str, str]) -> bool:
        """Execute Python script in current context"""
        script_content = self.core.files.read_str(script_path)

        # Prepare environment
        env = env_vars or {}
        env['OSAF_CORE'] = self.core

        try:
            # Execute in a controlled environment
            exec_globals = {'osaf': self.core, 'log': self.log, 'env': env}
            exec(script_content, exec_globals)
            return True
        except Exception as e:
            raise ScriptExecutionError(f"Python script error: {e}")

    def _execute_shell_script(self, script_path: str, env_vars: Dict[str, str]) -> bool:
        """Execute shell script"""
        env = os.environ.copy()
        env.update(env_vars or {})

        if self.core.utils.is_windows():
            cmd = ['cmd', '/c', script_path]
        else:
            cmd = ['bash', script_path]

        returncode, _ = self.core.processes.exec(cmd, env=env, log=True)
        return returncode == 0
