<?php
namespace boru\ai\Runtime;

class ToolRegistry
{
    /** @var ToolDefinition[] */
    protected $definitions = array();

    public function register($definition)
    {
        if ($definition instanceof ToolInterface) {
            if ($definition instanceof AbstractTool) {
                $definition = $definition->toToolDefinition();
            } else {
                $tool = $definition;
                $metadata = array(
                    'class' => get_class($tool),
                );
                if ($tool instanceof ToolPromptAdditionInterface) {
                    $promptAddition = trim((string)$tool->promptAddition());
                    if ($promptAddition !== '') {
                        $metadata['prompt_addition'] = $promptAddition;
                    }
                }
                $wrapped = new ToolDefinition();
                $wrapped->name($tool->name())
                    ->description($tool->description())
                    ->schema($tool->schema())
                    ->callback(function (array $arguments, ToolExecutionContext $context = null) use ($tool) {
                        return $tool->handle($arguments, $context);
                    })
                    ->metadata($metadata);
                $definition = $wrapped;
            }
        }

        if (!$definition instanceof ToolDefinition) {
            throw new \InvalidArgumentException('Tool registry expects a ToolDefinition or ToolInterface instance');
        }

        if (!$definition->name()) {
            throw new \InvalidArgumentException('Tool definition requires a name');
        }
        $this->definitions[$definition->name()] = $definition;
        return $this;
    }

    public function define($name, $description, array $schema, $callback)
    {
        $definition = new ToolDefinition();
        $definition->name($name)
            ->description($description)
            ->schema($schema)
            ->callback($callback);

        return $this->register($definition);
    }

    public function has($name)
    {
        return isset($this->definitions[$name]);
    }

    public function get($name)
    {
        if (!$this->has($name)) {
            throw new \InvalidArgumentException('Unknown tool: ' . $name);
        }
        return $this->definitions[$name];
    }

    public function all()
    {
        return $this->definitions;
    }

    public function exportSchemas()
    {
        $schemas = array();
        foreach ($this->definitions as $definition) {
            $schemas[] = $definition->toArray();
        }
        return $schemas;
    }
}
