<?php

declare(strict_types=1);

namespace Apexl\Tests\User\FeatureTests;

use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\TestInfrastructure\FeatureTest;
use PHPUnit\Framework\Attributes\Test;

final class RefreshTest extends FeatureTest
{
    private const string REFRESH_URI = '/api/v1/user/action/refresh';

    /**
     * The refresh call needs the (possibly expired) access token to recover the
     * session id, so without an Authorization header it cannot proceed — but
     * that is an unauthenticated caller, not a server fault. It used to answer
     * 500 because the JwtException fell through to the controller's catch-all.
     */
    #[Test]
    public function refreshWithoutAnAuthorizationHeaderIsUnauthorised(): void
    {
        ['refresh_token' => $refreshToken] = $this->login();

        $data = $this->post(self::REFRESH_URI, ['refresh_token' => $refreshToken], 401);

        $this->assertArrayHasKey('error', $data);
    }

    #[Test]
    public function refreshWithAMalformedAuthorizationHeaderIsUnauthorised(): void
    {
        ['refresh_token' => $refreshToken] = $this->login();

        $this->post(
            self::REFRESH_URI,
            ['refresh_token' => $refreshToken],
            401,
            ['Authorization' => 'not-a-bearer-token'],
        );
    }

    #[Test]
    public function refreshWithTheAccessTokenReturnsANewOne(): void
    {
        ['access_token' => $accessToken, 'refresh_token' => $refreshToken] = $this->login();

        $data = $this->post(
            self::REFRESH_URI,
            ['refresh_token' => $refreshToken],
            200,
            ['Authorization' => sprintf('Bearer %s', $accessToken)],
        );

        $this->assertIsString($data['access_token']);
    }

    /**
     * @return array{access_token: string, refresh_token: string}
     */
    private function login(): array
    {
        $email = $this->faker->unique()->email();
        $password = $this->faker->password();

        userEntity::factory()->create([
            'email' => $email,
            'password' => $password,
        ]);

        return $this->post('/api/v1/user/action/login', [
            'username' => $email,
            'password' => $password,
        ]);
    }
}
