<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Tools;

use Closure;
use JTL\DB\DbInterface;
use Plugin\tnt_mcp\src\Mcp\Contracts\Tool;
use Plugin\tnt_mcp\src\Mcp\Health\ShopHealthReport;
use Plugin\tnt_mcp\src\Mcp\Mode\EndpointClass;

/**
 * READ tool: "is anything wrong with this shop?", answered in one call with no arguments.
 *
 * This is the tool an LLM should reach for first, which drives every design decision in it:
 * it takes no arguments (nothing to get wrong), it always answers (a broken source degrades to an
 * amber signal, never to an exception — see {@see ShopHealthReport}), it costs a fixed ~900 tokens
 * regardless of shop size, and every non-green signal hands back a literal follow-up tool call
 * instead of prose. `verdict` is one machine-comparable word so a scheduled job can alert on it.
 */
final class ShopHealth implements Tool
{
    /**
     * @param Closure(): DbInterface $dbFactory must not touch the DB until run() — this tool is
     *                                          also enumerated for cheap metadata (scope listing)
     *                                          in contexts that never boot the shop container.
     */
    public function __construct(private readonly Closure $dbFactory)
    {
    }

    public function name(): string
    {
        return 'shop_health';
    }

    /** Kept under 140 characters (pinned by test) — this is the first line of a tool list. */
    public function description(): string
    {
        return 'Check the shop for trouble: errors, payment failures, stalled cron, setting changes. '
            . 'One call, no arguments. Start here.';
    }

    /** @return array<string,mixed> */
    public function inputSchema(): array
    {
        return [
            'type'                 => 'object',
            'properties'           => (object)[],
            'additionalProperties' => false,
        ];
    }

    public function isWrite(): bool
    {
        return false;
    }

    public function scope(): string
    {
        return 'shop:read';
    }

    public function endpointClass(): EndpointClass
    {
        return EndpointClass::Reversible;
    }

    /**
     * Arguments are accepted and ignored on purpose: a model that hallucinates `{since:'24h'}`
     * should get the health report, not a schema error on the one call that is meant to be safe.
     *
     * @param array<string,mixed> $args
     * @return array<string,mixed>
     */
    public function run(array $args): array
    {
        return (new ShopHealthReport(($this->dbFactory)()))->build();
    }
}
