<?php
namespace boru\ai\Runtime;

use boru\ai\Asset\AssetProviderRegistry;
use boru\ai\Asset\AssetStoreInterface;
use boru\ai\Asset\NullAssetStore;
use boru\ai\Embedding\EmbeddingStoreInterface;
use boru\ai\Embedding\NullEmbeddingStore;
use boru\ai\Mcp\McpClientFactoryInterface;
use boru\ai\Mcp\McpServerRegistry;
use boru\ai\Mcp\McpToolDiscoveryInterface;
use boru\ai\Mcp\McpToolInvokerInterface;
use boru\ai\Mcp\NullMcpClientFactory;
use boru\ai\Mcp\NullMcpToolDiscovery;
use boru\ai\Mcp\NullMcpToolInvoker;
use boru\ai\Persistence\NullPersistenceProvider;
use boru\ai\Persistence\PersistenceProviderInterface;
use boru\ai\Provider\ProviderRegistry;

class RuntimeContext
{
    /** @var ProviderRegistry */
    protected $providerRegistry;

    /** @var PersistenceProviderInterface */
    protected $persistenceProvider;

    /** @var AssetStoreInterface */
    protected $assetStore;

    /** @var AssetProviderRegistry */
    protected $assetProviderRegistry;

    /** @var EmbeddingStoreInterface */
    protected $embeddingStore;

    /** @var ToolRegistry */
    protected $toolRegistry;

    /** @var ToolExecutorInterface */
    protected $toolExecutor;

    /** @var ToolContext */
    protected $toolContext;

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

    /** @var McpClientFactoryInterface */
    protected $mcpClientFactory;

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

    /** @var McpToolDiscoveryInterface */
    protected $mcpToolDiscovery;

    public function __construct(ProviderRegistry $providerRegistry = null, PersistenceProviderInterface $persistenceProvider = null, AssetStoreInterface $assetStore = null, ToolExecutorInterface $toolExecutor = null, ToolRegistry $toolRegistry = null, ToolContext $toolContext = null, AssetProviderRegistry $assetProviderRegistry = null, McpServerRegistry $mcpServerRegistry = null, McpClientFactoryInterface $mcpClientFactory = null, McpToolInvokerInterface $mcpToolInvoker = null, McpToolDiscoveryInterface $mcpToolDiscovery = null, EmbeddingStoreInterface $embeddingStore = null)
    {
        $this->providerRegistry = $providerRegistry ? $providerRegistry : new ProviderRegistry();
        $this->persistenceProvider = $persistenceProvider ? $persistenceProvider : new NullPersistenceProvider();
        $this->assetStore = $assetStore ? $assetStore : new NullAssetStore();
        $this->assetProviderRegistry = $assetProviderRegistry ? $assetProviderRegistry : new AssetProviderRegistry();
        $this->embeddingStore = $embeddingStore ? $embeddingStore : new NullEmbeddingStore();
        $this->toolRegistry = $toolRegistry ? $toolRegistry : new ToolRegistry();
        $this->toolContext = $toolContext ? $toolContext : new ToolContext();
        $this->toolExecutor = $toolExecutor ? $toolExecutor : new ToolExecutor($this->toolRegistry, $this->toolContext->all());
        $this->mcpServerRegistry = $mcpServerRegistry ? $mcpServerRegistry : new McpServerRegistry();
        $this->mcpClientFactory = $mcpClientFactory ? $mcpClientFactory : new NullMcpClientFactory();
        $this->mcpToolInvoker = $mcpToolInvoker ? $mcpToolInvoker : new NullMcpToolInvoker();
        $this->mcpToolDiscovery = $mcpToolDiscovery ? $mcpToolDiscovery : new NullMcpToolDiscovery();
    }

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

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

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

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

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

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

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

    public function toolContext(ToolContext $toolContext = null)
    {
        if ($toolContext !== null) {
            $this->toolContext = $toolContext;
            if ($this->toolExecutor instanceof ToolExecutor) {
                $this->toolExecutor->contextValues($toolContext->all());
            }
            return $this;
        }
        return $this->toolContext;
    }

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

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

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

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