<?php

declare(strict_types=1);

namespace Apexl\Tests\User\UnitTests;

use apexl\Config\ConfigurationInterface;
use apexl\Config\ConfigurationMock;
use apexl\Io\modules\user\entities\RefreshToken;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\interfaces\JwtFromRequestServiceFactoryInterface;
use apexl\Io\modules\user\interfaces\TokenHasherInterface;
use apexl\Io\modules\user\services\JwtCreator;
use apexl\Io\modules\user\services\JwtFromRequestService;
use apexl\Io\modules\user\services\JwtKeyFromConfigService;
use apexl\Io\modules\user\services\RefreshTokenSessionIdFinder;
use apexl\Io\TestInfrastructure\UnitTest;
use PHPUnit\Framework\Attributes\Test;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Psr7\Factory\RequestFactory;
use function apexl\Io\container;

final class RefreshTokenSessionIdFinderTest extends UnitTest
{
    /**
     * @var mixed|null
     */
    private mixed $_serverName;

    #[Test]
    public function find(): void
    {
        $config = new ConfigurationMock([
            'auth.jwt.secret_key' => $this->faker->uuid(),
            'auth.jwt.algorithm' => 'HS256',
            'auth.jwt.lifetime' => 86400,
        ]);

        $user = userEntity::factory()->create();
        $sessionId = $this->faker->uuid();

        $token = container()->make(JwtCreator::class, [
            'config' => $config,
        ])->forUser(
            $user,
            $sessionId,
        );

        $refreshToken = new RefreshToken();
        $refreshToken->user_id = $user->id;
        $refreshToken->token = container()->get(TokenHasherInterface::class)->hash($this->faker->uuid());
        $refreshToken->expiry = 86400;


        $dummyFactory = $this->dummyJwtFromRequestServiceFactoryInterface($config);

        $request = container()->get(RequestFactory::class)
            ->createRequest('get', '/')
            ->withHeader('Authorization', sprintf('Bearer %s', $token));

        $found = container()->make(RefreshTokenSessionIdFinder::class, [
            'jwtFromRequestServiceFactory' => $dummyFactory,
        ])->find($request, $refreshToken);

        $this->assertSame($sessionId, $found);

    }

    private function dummyJwtFromRequestServiceFactoryInterface(ConfigurationMock $config): JwtFromRequestServiceFactoryInterface
    {
        return new readonly class($config) implements JwtFromRequestServiceFactoryInterface {
            public function __construct(private ConfigurationInterface $config) {}

            public function make(ServerRequestInterface $request): JwtFromRequestService
            {
                $keyService = container()->make(JwtKeyFromConfigService::class, ['config' => $this->config]);

                return new JwtFromRequestService($keyService, $request);
            }
        };
    }

    protected function setUp(): void
    {
        parent::setUp();
        $this->_serverName = $_SERVER['SERVER_NAME'] ?? null;
        $_SERVER['SERVER_NAME'] = 'serverName';
    }

    protected function tearDown(): void
    {
        parent::tearDown();
        $_SERVER['SERVER_NAME'] = $this->_serverName;
    }
}