<?php

declare(strict_types=1);

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

use JTL\DB\DbInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use Plugin\tnt_mcp\src\Mcp\OAuth\Entities\RefreshTokenEntity;
use stdClass;

/**
 * DB-backed refresh-token store (table tnt_mcp_oauth_refresh_token). Lets a connector renew its
 * access token; a missing/revoked row is rejected (deny-by-default).
 */
final class RefreshTokenRepository implements RefreshTokenRepositoryInterface
{
    public function __construct(private readonly DbInterface $db)
    {
    }

    public function getNewRefreshToken(): RefreshTokenEntityInterface
    {
        return new RefreshTokenEntity();
    }

    public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void
    {
        $row                 = new stdClass();
        $row->cToken         = $refreshTokenEntity->getIdentifier();
        $row->cAccessTokenId = $refreshTokenEntity->getAccessToken()->getIdentifier();
        $row->dExpires       = $refreshTokenEntity->getExpiryDateTime()->format('Y-m-d H:i:s');
        $row->nRevoked       = 0;
        $row->dCreated       = (new \DateTimeImmutable())->format('Y-m-d H:i:s');

        $this->db->insert('tnt_mcp_oauth_refresh_token', $row);
    }

    public function revokeRefreshToken(string $tokenId): void
    {
        $this->db->queryPrepared(
            'UPDATE tnt_mcp_oauth_refresh_token SET nRevoked = 1 WHERE cToken = :id',
            ['id' => $tokenId],
        );
    }

    public function isRefreshTokenRevoked(string $tokenId): bool
    {
        $row = $this->db->getSingleObject(
            'SELECT nRevoked FROM tnt_mcp_oauth_refresh_token WHERE cToken = :id',
            ['id' => $tokenId],
        );

        return $row === null || (int)$row->nRevoked === 1;
    }
}
