"""Shell tool — execute shell commands."""

from __future__ import annotations

import subprocess
import os
from typing import Any

from tsumugi.tools.base import BaseTool, PermissionLevel, ToolSpec


class ShellTool(BaseTool):
    """Execute a shell command and return its output."""

    def spec(self) -> ToolSpec:
        return ToolSpec(
            name="shell",
            description=(
                "Execute a shell command and return stdout/stderr. "
                "Commands run in the current working directory. "
                "Use for system commands, git, package managers, etc."
            ),
            parameters={
                "type": "object",
                "properties": {
                    "command": {
                        "type": "string",
                        "description": "The shell command to execute",
                    },
                    "timeout": {
                        "type": "integer",
                        "description": "Timeout in seconds. Default: 120",
                    },
                },
                "required": ["command"],
            },
            permission=PermissionLevel.EXECUTE,
        )

    def execute(self, **kwargs: Any) -> str:
        command = kwargs["command"]
        timeout = kwargs.get("timeout", 120)

        # Use bash on Unix, cmd on Windows (but prefer bash if available)
        shell_cmd = command
        use_shell = True

        try:
            result = subprocess.run(
                shell_cmd,
                shell=use_shell,
                capture_output=True,
                text=True,
                timeout=timeout,
                cwd=os.getcwd(),
                env={**os.environ},
            )
        except subprocess.TimeoutExpired:
            return f"Error: Command timed out after {timeout} seconds"
        except OSError as e:
            return f"Error executing command: {e}"

        output_parts = []
        if result.stdout:
            output_parts.append(result.stdout)
        if result.stderr:
            output_parts.append(f"[stderr]\n{result.stderr}")

        output = "\n".join(output_parts) if output_parts else "(no output)"

        # Truncate very long output
        max_output = 50000
        if len(output) > max_output:
            output = output[:max_output] + f"\n... (truncated, total {len(output)} chars)"

        if result.returncode != 0:
            output = f"Exit code: {result.returncode}\n{output}"

        return output
