import os
import subprocess
import tempfile
import shutil
from pathlib import Path


class DockerSandbox:
    """Simple sandbox using Docker container isolation"""

    def __init__(self, image: str = "python:3.9-slim"):
        self.image = image
        self.container_name = None

    def run_command(self, command: str, workdir: str = "/workspace") -> dict:
        """Run a command in the Docker sandbox"""
        try:
            # Create a temporary directory for workspace
            with tempfile.TemporaryDirectory() as temp_dir:
                # Copy current directory to temp workspace
                workspace = Path(temp_dir) / "workspace"
                workspace.mkdir()

                # For now, we'll just run in the current directory for simplicity
                # In a full implementation, we'd copy files to the container

                # Run command in Docker container
                result = subprocess.run(
                    [
                        "docker",
                        "run",
                        "--rm",
                        "-v",
                        f"{workspace}:/workspace",
                        "-w",
                        "/workspace",
                        self.image,
                        "bash",
                        "-c",
                        command,
                    ],
                    capture_output=True,
                    text=True,
                    timeout=30,
                )

                return {
                    "exit_code": result.returncode,
                    "stdout": result.stdout,
                    "stderr": result.stderr,
                    "success": result.returncode == 0,
                }
        except subprocess.TimeoutExpired:
            return {
                "exit_code": -1,
                "stdout": "",
                "stderr": "Command timed out after 30 seconds",
                "success": False,
            }
        except FileNotFoundError:
            # Docker not available, fall back to subprocess
            return self._run_subprocess_fallback(command, workdir)
        except Exception as e:
            return {
                "exit_code": -1,
                "stdout": "",
                "stderr": f"Sandbox error: {str(e)}",
                "success": False,
            }

    def _run_subprocess_fallback(self, command: str, workdir: str) -> dict:
        """Fallback to subprocess when Docker is not available"""
        try:
            original_cwd = os.getcwd()
            if workdir and os.path.exists(workdir):
                os.chdir(workdir)

            result = subprocess.run(
                command.split(), capture_output=True, text=True, timeout=30
            )

            return {
                "exit_code": result.returncode,
                "stdout": result.stdout,
                "stderr": result.stderr,
                "success": result.returncode == 0,
            }
        except subprocess.TimeoutExpired:
            return {
                "exit_code": -1,
                "stdout": "",
                "stderr": "Command timed out after 30 seconds",
                "success": False,
            }
        except Exception as e:
            return {
                "exit_code": -1,
                "stdout": "",
                "stderr": f"Subprocess error: {str(e)}",
                "success": False,
            }
        finally:
            os.chdir(original_cwd)


class SubprocessSandbox:
    """Simple sandbox using subprocess isolation"""

    def __init__(self):
        pass

    def run_command(self, command: str, workdir: str = ".") -> dict:
        """Run a command in the subprocess sandbox"""
        try:
            original_cwd = os.getcwd()
            if workdir and os.path.exists(workdir):
                os.chdir(workdir)

            # Security: basic command validation
            dangerous_commands = ["rm", "dd", "mkfs", "fdisk", "> /dev/sda"]
            if any(cmd in command for cmd in dangerous_commands):
                return {
                    "exit_code": -1,
                    "stdout": "",
                    "stderr": f"Dangerous command blocked: {command}",
                    "success": False,
                }

            result = subprocess.run(
                command.split(), capture_output=True, text=True, timeout=30
            )

            return {
                "exit_code": result.returncode,
                "stdout": result.stdout,
                "stderr": result.stderr,
                "success": result.returncode == 0,
            }
        except subprocess.TimeoutExpired:
            return {
                "exit_code": -1,
                "stdout": "",
                "stderr": "Command timed out after 30 seconds",
                "success": False,
            }
        except Exception as e:
            return {
                "exit_code": -1,
                "stdout": "",
                "stderr": f"Subprocess error: {str(e)}",
                "success": False,
            }
        finally:
            os.chdir(original_cwd)


# Factory function to get appropriate sandbox
def get_sandbox(backend: str = "subprocess"):
    """Get a sandbox instance based on backend"""
    if backend == "docker":
        return DockerSandbox()
    else:
        return SubprocessSandbox()
