<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\Tools;

use Closure;
use Plugin\tnt_mcp\src\Mcp\Analytics\AnalyticsQuery;
use Plugin\tnt_mcp\src\Mcp\Analytics\OrderReader;
use Plugin\tnt_mcp\src\Mcp\Contracts\Tool;
use Plugin\tnt_mcp\src\Mcp\Mode\EndpointClass;
use RuntimeException;

/**
 * READ tool: find an order by number, customer name, company or e-mail.
 *
 * Split from {@see ListOrders} on purpose. They share a reader and a filter object, but they answer
 * different questions and the tool list is the model's only routing hint: "show me last week's
 * orders" and "find Müller's order" should not both land on one tool with an optional argument that
 * changes what the tool is for.
 *
 * The window still applies and still defaults to 30 days — a search that quietly scanned all history
 * would be the slow query that takes a shop down. The response says so when it finds nothing.
 */
final class SearchOrders implements Tool
{
    private const ARGS = ['search', 'since', 'until', 'status', 'limit', 'offset'];

    /** @param Closure(): OrderReader $readerFactory must not touch the DB until run() */
    public function __construct(private readonly Closure $readerFactory)
    {
    }

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

    public function description(): string
    {
        return 'Find orders by order number, customer name, company or e-mail within a time window.';
    }

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

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

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

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

    /**
     * @param array<string,mixed> $args
     * @return array<string,mixed>
     */
    public function run(array $args): array
    {
        $query = AnalyticsQuery::fromArgs($this->name(), $args, self::ARGS);
        if ($query->search === null) {
            throw new RuntimeException('search_orders: "search" is required and must not be empty.');
        }

        $result           = ($this->readerFactory)()->orders($query);
        $result['search'] = $query->search;
        $notes            = $query->notes;
        if ($result['total'] === 0) {
            $notes[] = 'Nothing matched inside the window. The search is a literal substring, and '
                . 'the window defaults to the last ' . AnalyticsQuery::DEFAULT_SINCE
                . ' — widen it with since before concluding the order does not exist.';
        }
        $result['notes'] = $notes;

        return $result;
    }
}
