"""Code runner tool - Execute Python code safely."""

from __future__ import annotations

import subprocess
import tempfile
import os
from typing import Any

from agenai.agent.tools.base import Tool, ToolResult


class CodeRunnerTool(Tool):
    """Execute Python code safely in a subprocess."""

    @property
    def name(self) -> str:
        return "run_code"

    @property
    def description(self) -> str:
        return """Execute Python code and return the output.

Use this to:
- Demonstrate how code works
- Test student solutions
- Show expected output for examples"""

    @property
    def parameters(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "code": {
                    "type": "string",
                    "description": "Python code to execute",
                },
                "timeout": {
                    "type": "integer",
                    "description": "Execution timeout in seconds (default: 10)",
                    "default": 10,
                },
                "input_data": {
                    "type": "string",
                    "description": "Input to provide to the program via stdin",
                },
            },
            "required": ["code"],
        }

    def execute(
        self,
        code: str,
        timeout: int = 10,
        input_data: str | None = None,
    ) -> ToolResult:
        """Execute Python code and return results."""
        try:
            # Write code to temp file for better error messages
            with tempfile.NamedTemporaryFile(
                mode="w",
                suffix=".py",
                delete=False,
            ) as f:
                f.write(code)
                temp_path = f.name

            try:
                result = subprocess.run(
                    ["python", temp_path],
                    capture_output=True,
                    text=True,
                    timeout=timeout,
                    input=input_data,
                )

                output_parts = []

                if result.stdout:
                    output_parts.append(f"Output:\n{result.stdout}")

                if result.stderr:
                    output_parts.append(f"Errors:\n{result.stderr}")

                if result.returncode != 0:
                    output_parts.append(f"Exit code: {result.returncode}")

                if not output_parts:
                    output_parts.append("(No output)")

                output = "\n".join(output_parts)

                if result.returncode == 0:
                    return ToolResult.ok(output)
                else:
                    return ToolResult.fail(output)

            finally:
                os.unlink(temp_path)

        except subprocess.TimeoutExpired:
            return ToolResult.fail(
                f"Code execution timed out after {timeout} seconds. "
                "This might indicate an infinite loop."
            )
        except Exception as e:
            return ToolResult.fail(f"Error executing code: {e}")
