"""CLI tool wrappers — turn any command-line tool into an agent tool."""
from __future__ import annotations

import asyncio
import shlex

from logos_adk.tools import Tool


def cli_tool(
    command: str,
    *,
    name: str | None = None,
    description: str | None = None,
    timeout: float = 120.0,
    shell: bool = False,
) -> Tool:
    """Create a Tool that runs a CLI command with a prompt argument.

    The command receives the prompt as stdin and returns stdout as the result.

    Args:
        command: The CLI command to run (e.g., "claude", "codex", "gemini").
        name: Tool name (defaults to the command base name).
        description: Tool description.
        timeout: Max seconds to wait for the command.
        shell: If True, run via shell (needed for pipes, etc.).

    Usage::

        # Claude Code as a tool
        claude = cli_tool(
            "claude -p",
            name="claude_code",
            description="Ask Claude Code to solve a coding task",
        )

        # Codex CLI
        codex = cli_tool(
            "codex --quiet",
            name="codex",
            description="Ask OpenAI Codex to solve a task",
        )

        # Any CLI tool
        my_tool = cli_tool("python my_script.py", name="my_script")

        agent = Agent("orchestrator").tools([claude, codex])
    """
    cmd_parts = shlex.split(command)
    tool_name = name or cmd_parts[0].split("/")[-1]
    tool_desc = description or f"Run '{command}' CLI tool"
    cmd = command

    async def _run_cli(prompt: str) -> str:
        proc = None
        try:
            if shell:
                proc = await asyncio.create_subprocess_shell(
                    f'{cmd} "{prompt}"' if "{}" not in cmd else cmd.replace("{}", prompt),
                    stdout=asyncio.subprocess.PIPE,
                    stderr=asyncio.subprocess.PIPE,
                )
            else:
                proc = await asyncio.create_subprocess_exec(
                    *cmd_parts,
                    stdin=asyncio.subprocess.PIPE,
                    stdout=asyncio.subprocess.PIPE,
                    stderr=asyncio.subprocess.PIPE,
                )
            stdout, stderr = await asyncio.wait_for(
                proc.communicate(input=prompt.encode() if not shell else None),
                timeout=timeout,
            )
            output = stdout.decode().strip()
            if proc.returncode != 0 and not output:
                err = stderr.decode().strip()
                return f"Error (exit code {proc.returncode}): {err}"
            return output
        except asyncio.TimeoutError:
            if proc is not None and proc.returncode is None:
                proc.kill()
                await proc.wait()
            return f"Error: command timed out after {timeout}s"
        except FileNotFoundError:
            return f"Error: command '{cmd_parts[0]}' not found"

    return Tool(fn=_run_cli, name=tool_name, description=tool_desc)


def claude_code_tool(
    *,
    name: str = "claude_code",
    description: str = "Delegate a coding task to Claude Code CLI",
    model: str | None = None,
    timeout: float = 300.0,
) -> Tool:
    """Create a tool that delegates to Claude Code CLI.

    Requires ``claude`` CLI to be installed and authenticated.
    """
    cmd = "claude -p"
    if model:
        cmd += f" --model {model}"

    return cli_tool(cmd, name=name, description=description, timeout=timeout)


def codex_tool(
    *,
    name: str = "codex",
    description: str = "Delegate a coding task to OpenAI Codex CLI",
    timeout: float = 300.0,
) -> Tool:
    """Create a tool that delegates to OpenAI Codex CLI.

    Requires ``codex`` CLI to be installed and authenticated.
    """
    return cli_tool(
        "codex --quiet",
        name=name,
        description=description,
        timeout=timeout,
    )


def gemini_tool(
    *,
    name: str = "gemini",
    description: str = "Delegate a task to Gemini CLI",
    timeout: float = 300.0,
) -> Tool:
    """Create a tool that delegates to Gemini CLI.

    Requires ``gemini`` CLI to be installed and authenticated.
    """
    return cli_tool(
        "gemini -p",
        name=name,
        description=description,
        timeout=timeout,
    )
