<?php

declare(strict_types=1);

namespace NoahVet\Reef\Test\A_Unit\Security\User\Provider;

use NoahVet\Reef\Exception\NotJWTException;
use NoahVet\Reef\Security\Token\JWTDecoderInterface;
use NoahVet\Reef\Security\User\Provider\JWTReefOAuthUserProvider;
use NoahVet\Reef\Security\User\ReefOAuthUser;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Clock\Clock;
use Symfony\Component\Clock\NativeClock;

class JWTReefOAuthUserProviderTest extends TestCase
{
    /**
     * @var JWTDecoderInterface&MockObject
     */
    private JWTDecoderInterface $decoder;

    private JWTReefOAuthUserProvider $provider;

    protected function setUp(): void
    {
        $this->decoder = $this->createMock(JWTDecoderInterface::class);

        $this->provider = new JWTReefOAuthUserProvider($this->decoder);
    }

    protected function tearDown(): void
    {
        Clock::set(new NativeClock());
    }

    public function testLoadUserOK(): void
    {
        $this->decoder
            ->expects($this->once())
            ->method('decodeJWT')
            ->with('bearer_token')
            ->willReturn((object) [
                'sub' => '92c24f57-f339-46d4-bba6-2cf69690b1a0',
            ])
        ;

        $user = $this->provider->loadUser('bearer_token');

        $this->assertInstanceOf(ReefOAuthUser::class, $user);
        $this->assertEquals('reef:iam:principal:92c24f57-f339-46d4-bba6-2cf69690b1a0', $user->getUserIdentifier());
    }

    public function testLoadUserIncorrectToken(): void
    {
        $this->decoder
            ->expects($this->once())
            ->method('decodeJWT')
            ->with('invalid_token')
            ->willThrowException(new NotJWTException())
        ;

        $this->expectException(NotJWTException::class);

        $this->provider->loadUser('invalid_token');
    }
}
