<?php
namespace boru\ai\Mcp;

use boru\ai\Runtime\ToolDefinition;
use boru\ai\Runtime\ToolRegistry;

class McpToolRegistrar
{
    /** @var ToolRegistry */
    protected $toolRegistry;

    /** @var McpToolInvokerInterface */
    protected $toolInvoker;

    /** @var McpServerRegistry */
    protected $serverRegistry;

    public function __construct(ToolRegistry $toolRegistry = null, McpToolInvokerInterface $toolInvoker = null, McpServerRegistry $serverRegistry = null)
    {
        $this->toolRegistry = $toolRegistry ? $toolRegistry : new ToolRegistry();
        $this->toolInvoker = $toolInvoker ? $toolInvoker : new NullMcpToolInvoker();
        $this->serverRegistry = $serverRegistry ? $serverRegistry : new McpServerRegistry();
    }

    public function toolRegistry(ToolRegistry $toolRegistry = null)
    {
        if ($toolRegistry !== null) {
            $this->toolRegistry = $toolRegistry;
            return $this;
        }
        return $this->toolRegistry;
    }

    public function toolInvoker(McpToolInvokerInterface $toolInvoker = null)
    {
        if ($toolInvoker !== null) {
            $this->toolInvoker = $toolInvoker;
            return $this;
        }
        return $this->toolInvoker;
    }

    public function serverRegistry(McpServerRegistry $serverRegistry = null)
    {
        if ($serverRegistry !== null) {
            $this->serverRegistry = $serverRegistry;
            return $this;
        }
        return $this->serverRegistry;
    }

    public function register($serverName, array $tool)
    {
        $this->assertKnownServer($serverName);

        $definition = McpToolAdapter::toToolDefinition($serverName, $tool, $this->toolInvoker());
        $this->toolRegistry()->register($definition);

        return $definition;
    }

    public function registerMany($serverName, array $tools)
    {
        $definitions = array();

        foreach ($tools as $tool) {
            if (!is_array($tool)) {
                continue;
            }

            $definitions[] = $this->register($serverName, $tool);
        }

        return $definitions;
    }

    protected function assertKnownServer($serverName)
    {
        $serverName = is_string($serverName) ? trim($serverName) : '';
        if ($serverName === '') {
            throw new \InvalidArgumentException('MCP server name is required');
        }

        if (!$this->serverRegistry()->has($serverName)) {
            throw new \InvalidArgumentException('Unknown MCP server: ' . $serverName);
        }
    }
}
