<?php

declare(strict_types=1);

namespace Apexl\Tests\User\UnitTests;

use apexl\Config\ConfigurationMock;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\interfaces\JwtKeyProviderInterface;
use apexl\Io\modules\user\services\JwtCreator;
use apexl\Io\TestInfrastructure\UnitTest;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use PHPUnit\Framework\Attributes\Test;
use function apexl\Io\container;

/**
 * Regression for the `$_SERVER['SERVER_NAME']` fragility (Plan 007 §6): on SAPIs
 * that don't populate SERVER_NAME the issuer was null. It must now fall back to
 * the configured backend domain's host.
 */
final class JwtCreatorServerNameFallbackTest extends UnitTest
{
    private const string SECRET = 'server-name-fallback-secret-0123456789abcdef';

    #[Test]
    public function issuerFallsBackToBackendDomainWhenServerNameAbsent(): void
    {
        $originalServerName = $_SERVER['SERVER_NAME'] ?? null;
        unset($_SERVER['SERVER_NAME']);

        try {
            $config = new ConfigurationMock([
                'auth.jwt.secret_key' => self::SECRET,
                'auth.jwt.algorithm' => 'HS256',
                'auth.jwt.lifetime' => 1200,
                'http.backend_domain' => 'https://goshawk.example.test',
            ]);

            $user = userEntity::factory()->create(['id' => 4242], false);
            $jwt = container()->make(JwtCreator::class, ['config' => $config])
                ->forUser($user, 'session-id-abc');

            $key = container()->make(JwtKeyProviderInterface::class, ['config' => $config])->key();

            try {
                $decoded = JWT::decode($jwt, $key);
            } catch (ExpiredException $e) {
                $decoded = $e->getPayload();
            }

            $this->assertSame('goshawk.example.test', $decoded->iss);
        } finally {
            if ($originalServerName !== null) {
                $_SERVER['SERVER_NAME'] = $originalServerName;
            }
        }
    }

    #[Test]
    public function explicitServerNameStillWins(): void
    {
        $config = new ConfigurationMock([
            'auth.jwt.secret_key' => self::SECRET,
            'auth.jwt.algorithm' => 'HS256',
            'auth.jwt.lifetime' => 1200,
            'http.backend_domain' => 'https://goshawk.example.test',
        ]);

        $user = userEntity::factory()->create(['id' => 99], false);
        $jwt = container()->make(JwtCreator::class, ['config' => $config])
            ->forUser($user, 'sid', null, 'explicit.example');

        $key = container()->make(JwtKeyProviderInterface::class, ['config' => $config])->key();

        try {
            $decoded = JWT::decode($jwt, $key);
        } catch (ExpiredException $e) {
            $decoded = $e->getPayload();
        }

        $this->assertSame('explicit.example', $decoded->iss);
    }
}
