<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Contracts;

/**
 * A second plugin's entry point into this plugin's MCP tool surface. The provider implements the
 * *existing* {@see Tool} contract for each tool it contributes — that is the whole point of the
 * seam: tnt_mcp learns nothing about the other plugin beyond this interface.
 *
 * Registration happens through {@see \Plugin\tnt_mcp\src\Mcp\ToolRegistry::register()}, typically
 * from the providing plugin's `Bootstrap::boot()` behind a bare `class_exists()` check, so neither
 * plugin hard-depends on the other.
 *
 * ⚠️ {@see ToolProvider::tools()} MUST be side-effect-free and MUST NOT touch the shop runtime
 * (no `Shop::Container()`, no DB, no Smarty). It is also called by
 * {@see \Plugin\tnt_mcp\src\Mcp\OAuth\ScopeCatalog} in cheap-metadata contexts where the container
 * is never booted. Wrap every dependency in a closure the tool resolves inside `run()` — exactly
 * the discipline {@see \Plugin\tnt_mcp\src\Mcp\ToolFactory} already follows for its own tools.
 */
interface ToolProvider
{
    /** Stable machine id of the providing plugin, e.g. "tnt_workflows". Registration is idempotent per id. */
    public function providerId(): string;

    /**
     * The {@see \Plugin\tnt_mcp\src\Mcp\ToolRegistry::API_VERSION} this provider was built
     * against. A version outside the registry's supported range makes the provider be skipped
     * (logged, never fatal) rather than risking a half-compatible tool surface.
     */
    public function apiVersion(): int;

    /**
     * The tools this provider contributes, built lazily and without touching the shop runtime.
     *
     * @return list<Tool>
     */
    public function tools(): array;
}
