"""
RemoteTool.
Wrapper around a connector that calls a remote tool.
"""
from typing import Optional
from openspace.utils.logging import Logger
from ..types import BackendType, ToolResult, ToolSchema, ToolStatus
from .base import BaseTool
from openspace.grounding.core.transport.connectors import BaseConnector

logger = Logger.get_logger(__name__)


class RemoteTool(BaseTool):
    """Wrapper around a connector that calls a remote tool (MCP/LSP).

    ``MCPTool`` — isReadOnly: false (default),
    isConcurrencySafe: false (default). MCP tool capabilities are
    unknown at definition time, so we conservatively use the safe
    defaults (all False). The auto-defer logic in
    ``BaseTool.bind_runtime_info`` will automatically defer MCP tools
    from the initial prompt.
    """

    backend_type = BackendType.NOT_SET
    
    def __init__(
        self,
        schema: ToolSchema | None = None,
        connector: Optional[BaseConnector] = None,
        remote_name: str = "",
        *,
        verbose: bool = False,
        backend: BackendType = BackendType.NOT_SET,
    ):
        self._conn = connector
        self._remote_name = remote_name or (schema.name if schema else "")
        self.backend_type = backend
        super().__init__(schema=schema, verbose=verbose)

    async def _arun(self, **kwargs):
        # If no connector, tool must be invoked via grounding_client (on-demand startup)
        if self._conn is None:
            raise RuntimeError(
                f"Tool '{self.name}' has no connector. "
                "Use grounding_client.invoke_tool() to execute it with on-demand server startup."
            )
        
        raw = await self._conn.invoke(self._remote_name, kwargs)
        
        if hasattr(raw, 'content') and hasattr(raw, 'isError'):
            content_parts = []
            for item in (raw.content or []):
                # Extract text from TextContent
                if hasattr(item, 'text') and item.text:
                    content_parts.append(item.text)
                # Handle ImageContent (just note its presence)
                elif hasattr(item, 'data'):
                    content_parts.append(f"[Image data: {len(item.data) if item.data else 0} bytes]")
                # Handle EmbeddedResource
                elif hasattr(item, 'resource'):
                    content_parts.append(f"[Embedded resource: {getattr(item.resource, 'uri', 'unknown')}]")
            
            content = "\n".join(content_parts) if content_parts else ""
            is_error = getattr(raw, 'isError', False)
            
            return ToolResult(
                status=ToolStatus.ERROR if is_error else ToolStatus.SUCCESS,
                content=content,
                error=content if is_error else None,
            )
        
        # Handle dict response
        if isinstance(raw, dict):
            import json
            try:
                content = json.dumps(raw, ensure_ascii=False, indent=2)
            except (TypeError, ValueError):
                content = str(raw)
        # Handle list/tuple response
        elif isinstance(raw, (list, tuple)):
            import json
            try:
                content = json.dumps(raw, ensure_ascii=False, indent=2)
            except (TypeError, ValueError):
                content = str(raw)
        # Handle primitive types
        elif isinstance(raw, (int, float, bool)):
            content = str(raw)
        elif isinstance(raw, str):
            content = raw
        # Fallback for unknown types
        else:
            content = str(raw)
        
        return ToolResult(
            status=ToolStatus.SUCCESS,
            content=content,
        )