import os
import subprocess
from openharness.tools.tool import Tool


class RunTestsTool(Tool):
    """Tool to run tests in the project"""
    
    def __init__(self, base_dir=None, sandbox=None):
        super().__init__("run_tests")
        if base_dir is not None:
            self.base_dir = os.path.abspath(base_dir)
        else:
            self.base_dir = None
        self.sandbox = sandbox
    
    def run(self, test_command: str = "python -m pytest", path: str = ".") -> str:
        """Run tests using the specified command"""
        # Determine base directory
        if self.base_dir is not None:
            base = self.base_dir
        else:
            base = os.getcwd()
        
        # If path is ".", use base_dir, otherwise join with base
        if path == ".":
            test_root = base
        else:
            test_root = os.path.abspath(os.path.join(base, path))
        
        # Resolve to real paths for security check
        real_base = os.path.realpath(base)
        real_test_root = os.path.realpath(test_root)
        
        # Security: ensure the test root is within the base directory
        if not real_test_root.startswith(real_base + os.sep) and real_test_root != real_base:
            return f"Error: Access to path '{path}' is not allowed for security reasons"
        
        # If no sandbox provided, fall back to subprocess
        if self.sandbox is None:
            try:
                # Change to the test directory
                original_cwd = os.getcwd()
                os.chdir(real_test_root)
                
                try:
                    # Run the test command
                    result = subprocess.run(
                        test_command.split(),
                        capture_output=True,
                        text=True,
                        timeout=30
                    )
                    
                    output = f"Exit code: {result.returncode}\n"
                    if result.stdout:
                        output += f"STDOUT:\n{result.stdout}\n"
                    if result.stderr:
                        output += f"STDERR:\n{result.stderr}\n"
                    
                    return output.strip()
                finally:
                    os.chdir(original_cwd)
                    
            except subprocess.TimeoutExpired:
                return "Error: Test execution timed out (30 seconds)"
            except Exception as e:
                return f"Error running tests: {str(e)}"
        else:
            # Use sandbox
            try:
                result = self.sandbox.run_command(test_command, workdir=real_test_root)
                
                output = f"Exit code: {result['exit_code']}\n"
                if result['stdout']:
                    output += f"STDOUT:\n{result['stdout']}\n"
                if result['stderr']:
                    output += f"STDERR:\n{result['stderr']}\n"
                
                return output.strip()
            except Exception as e:
                return f"Error running tests in sandbox: {str(e)}"
    
    def get_description(self) -> str:
        return "Run tests in the project"
