"""
Python Runtime

Native Python tool execution runtime.
"""

import asyncio
import importlib.util
import sys
from pathlib import Path
from typing import Any, Callable, Dict

from tools.runtime.base import BaseRuntime


class PythonRuntime(BaseRuntime):
    """Python runtime for executing Python-based tools"""

    def __init__(self):
        self._executors: Dict[str, Callable] = {}
        self._modules: Dict[str, Any] = {}

    def get_name(self) -> str:
        return "python"

    async def validate(self, entry: str) -> bool:
        """Validate Python tool entry point"""
        path = Path(entry)
        if not path.exists():
            return False
        if path.suffix != ".py":
            return False
        return True

    async def execute(
        self,
        entry: str,
        command: str,
        parameters: Dict[str, Any],
        timeout: int,
    ) -> Dict[str, Any]:
        """Execute a Python tool"""
        try:
            # Load module dynamically
            module = self._load_module(entry, command)
            if module is None:
                return {
                    "status": "error",
                    "error": f"Failed to load module from {entry}",
                }

            # Get the execute function
            if not hasattr(module, "execute"):
                return {
                    "status": "error",
                    "error": "Module does not have 'execute' function",
                }

            execute_func = module.execute

            # Run in executor to avoid blocking
            loop = asyncio.get_event_loop()
            result = await asyncio.wait_for(
                loop.run_in_executor(
                    None,
                    lambda: execute_func(command, parameters),
                ),
                timeout=timeout / 1000,
            )

            return {
                "status": "success",
                "result": result,
            }

        except asyncio.TimeoutError:
            return {
                "status": "error",
                "error": f"Execution timed out after {timeout}ms",
            }
        except Exception as e:
            return {
                "status": "error",
                "error": str(e),
            }

    def _load_module(self, entry: str, command: str) -> Any:
        """Load Python module from file path"""
        cache_key = f"{entry}:{command}"
        if cache_key in self._modules:
            return self._modules[cache_key]

        try:
            path = Path(entry)
            module_name = path.stem

            spec = importlib.util.spec_from_file_location(module_name, entry)
            if spec is None or spec.loader is None:
                return None

            module = importlib.util.module_from_spec(spec)
            sys.modules[module_name] = module
            spec.loader.exec_module(module)

            self._modules[cache_key] = module
            return module

        except Exception:
            return None

    def clear_cache(self) -> None:
        """Clear module cache"""
        self._modules.clear()
