<?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: what actually sold, ranked by net line revenue or by units.
 *
 * "Best-selling" is two different lists and the difference matters to the shop owner, so the ranking
 * is an explicit argument rather than a silent choice. Coupon and shipping rows are excluded
 * (`nPosTyp = 1`); leaving them in is the classic way a hand-written query invents a top seller
 * called "Versandkosten".
 */
final class TopProducts implements Tool
{
    private const ARGS = ['since', 'until', 'status', 'limit'];

    private const RANKINGS = ['revenue', 'quantity'];

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

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

    public function description(): string
    {
        return 'Best-selling products in a window, ranked by net revenue or by units sold, with '
            . 'quantity and order count.';
    }

    /** @return array<string,mixed> */
    public function inputSchema(): array
    {
        return [
            'type'       => 'object',
            'properties' => AnalyticsQuery::schemaFor(self::ARGS) + [
                'rankBy' => [
                    'type'        => 'string',
                    'enum'        => self::RANKINGS,
                    'description' => 'Ranking criterion; defaults to "revenue". '
                        . 'Use "quantity" for units sold.',
                ],
            ],
            '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
    {
        $rankBy = $args['rankBy'] ?? 'revenue';
        if (!\is_string($rankBy) || !\in_array($rankBy, self::RANKINGS, true)) {
            throw new RuntimeException(
                'top_products: "rankBy" must be one of: ' . \implode(', ', self::RANKINGS) . '.'
            );
        }

        $query  = AnalyticsQuery::fromArgs($this->name(), $args, self::ARGS);
        $result = ($this->readerFactory)()->topProducts($query, $rankBy);

        $result['notes'] = \array_merge($query->notes, $result['notes']);

        return $result;
    }
}
