<?php

declare(strict_types=1);

namespace Plugin\tnt_mcp\src\Mcp\OAuth\Repositories;

use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use Plugin\tnt_mcp\src\Mcp\OAuth\Entities\ScopeEntity;
use Plugin\tnt_mcp\src\Mcp\OAuth\ScopeCatalog;

/**
 * Resolves + finalises scopes against the {@see ScopeCatalog}. An unknown scope resolves to null,
 * which makes league reject the request — deny-by-default. finalizeScopes() intersects the request
 * with the catalog (never widens it) and, if a request carried no scope at all, grants the shop's
 * full default set so the single shop identity acts with its intended reach.
 */
final class ScopeRepository implements ScopeRepositoryInterface
{
    public function getScopeEntityByIdentifier(string $identifier): ?ScopeEntityInterface
    {
        // The empty check is redundant against the catalog (it never holds '') but states the
        // invariant league's ScopeEntity requires: an identifier is a non-empty string.
        if ($identifier === '' || !ScopeCatalog::knows($identifier)) {
            return null;
        }
        $scope = new ScopeEntity();
        $scope->setIdentifier($identifier);

        return $scope;
    }

    /**
     * @param list<ScopeEntityInterface> $scopes
     *
     * @return list<ScopeEntityInterface>
     */
    public function finalizeScopes(
        array $scopes,
        string $grantType,
        ClientEntityInterface $clientEntity,
        ?string $userIdentifier = null,
        ?string $authCodeId = null,
    ): array {
        $identifiers = [];
        foreach ($scopes as $scope) {
            $id = $scope->getIdentifier();
            if (ScopeCatalog::knows($id) && !\in_array($id, $identifiers, true)) {
                $identifiers[] = $id;
            }
        }

        // No usable scope requested → grant the shop's full default set.
        if ($identifiers === []) {
            $identifiers = ScopeCatalog::all();
        }

        $out = [];
        foreach ($identifiers as $id) {
            $entity = new ScopeEntity();
            $entity->setIdentifier($id);
            $out[] = $entity;
        }

        return $out;
    }
}
