<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Contracts;

use Plugin\tnt_mcp\src\Mcp\Mode\EndpointClass;

/**
 * Opt-in refinement of {@see Tool::endpointClass()} for the one tool whose reversibility is not a
 * property of the tool at all: `invoke_admin_action` fronts catalog entries of BOTH classes, so the
 * class the {@see \Plugin\tnt_mcp\src\Mcp\Mode\ModeGuard} has to judge is only knowable once the
 * arguments name an entry (design §9 Q5).
 *
 * It is a **separate, narrow interface** rather than a change to {@see Tool} on purpose: thirteen
 * shipped tools implement `Tool` and `ToolFactoryTest` pins them, and widening a contract that
 * thirteen classes satisfy in order to serve one is how a contract stops meaning anything.
 *
 * ## `null` is the whole point
 *
 * An id that cannot be resolved — unknown, or withheld by the Q7 version gate — MUST return `null`,
 * not a guess and not `Reversible`. `ModeGuard::permits()` denies a null class in `limited` mode
 * (`ModeGuard.php:23-30`), which is the shipped default (`info.xml` `initialValue="limited"`), so an
 * unresolvable id fails **closed** through the existing `denied:mode` audit path. Returning
 * `Destructive` would work in limited mode and be wrong in full mode; returning `Reversible` would
 * be wrong everywhere.
 */
interface PerCallEndpointClass
{
    /**
     * @param array<string,mixed> $args the arguments this call was made with
     * @return ?EndpointClass the class of the entry these arguments address, or null when the
     *                        arguments do not resolve to an available entry (fail closed)
     */
    public function endpointClassFor(array $args): ?EndpointClass;
}
