<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Admin;

use Plugin\tnt_mcp\src\Mcp\Contracts\Tool;
use Plugin\tnt_mcp\src\Mcp\Contracts\ToolProvider;
use Plugin\tnt_mcp\src\Mcp\ToolRegistry;
use Throwable;

/**
 * What other plugins contribute to this server's tool surface — the visible half of the
 * cross-plugin seam (design §1.4).
 *
 * Without this the failure mode is silent: a sibling plugin built against a newer registry version
 * is skipped, and the merchant just sees tools that used to be there stop existing. Every accepted
 * provider, every rejected one **and the reason** are rendered on the Integrations tab.
 *
 * Read-only and exception-free: a broken provider must not take the admin page down either.
 */
final class PluginProvidersReport
{
    /**
     * @return list<array{
     *     id: string,
     *     ok: bool,
     *     toolCount: int,
     *     tools: list<string>,
     *     reason: string,
     *     notices: list<string>,
     *     noticeCount: int
     * }>
     */
    public function build(): array
    {
        $rows = [];

        foreach (ToolRegistry::providers() as $provider) {
            $id      = $this->providerId($provider);
            $tools   = $this->toolNames($provider);
            $notices = ToolRegistry::notices()[$id] ?? [];
            $rows[]  = [
                'id'          => $id,
                'ok'          => true,
                'toolCount'   => \count($tools),
                'tools'       => $tools,
                'reason'      => '',
                'notices'     => $notices,
                // Smarty cannot count an array without a PHP-function modifier, and the notice
                // count is what the collapsed "N Hinweise" summary is labelled with (ledger U12).
                'noticeCount' => \count($notices),
            ];
        }

        foreach (ToolRegistry::skipped() as $id => $reason) {
            $notices = ToolRegistry::notices()[$id] ?? [];
            $rows[]  = [
                'id'          => $id,
                'ok'          => false,
                'toolCount'   => 0,
                'tools'       => [],
                'reason'      => $reason,
                'notices'     => $notices,
                'noticeCount' => \count($notices),
            ];
        }

        return $rows;
    }

    private function providerId(ToolProvider $provider): string
    {
        try {
            return $provider->providerId();
        } catch (Throwable) {
            return '?';
        }
    }

    /**
     * @return list<string>
     */
    private function toolNames(ToolProvider $provider): array
    {
        try {
            return \array_map(static fn (Tool $tool): string => $tool->name(), $provider->tools());
        } catch (Throwable) {
            return [];
        }
    }
}
