<?php

namespace App\Tests\Controller\Api;

use App\Controller\Api\ApiAuthController;
use PHPUnit\Framework\TestCase;

class ApiAuthControllerTest extends TestCase
{
    private const SECRET = 'test_secret_key_for_jwt';

    private function generateToken(array $payloadOverrides = []): string
    {
        $header = $this->base64UrlEncode(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
        $payload = array_merge([
            'userId' => 42,
            'email' => 'orga@test.com',
            'roles' => ['ROLE_ORGANIZER'],
            'iat' => time(),
            'exp' => time() + 86400,
        ], $payloadOverrides);
        $payloadB64 = $this->base64UrlEncode(json_encode($payload));
        $signature = $this->base64UrlEncode(hash_hmac('sha256', $header.'.'.$payloadB64, self::SECRET, true));

        return $header.'.'.$payloadB64.'.'.$signature;
    }

    private function base64UrlEncode(string $data): string
    {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }

    public function testVerifyJwtValid(): void
    {
        $token = $this->generateToken();
        $result = ApiAuthController::verifyJwt($token, 'orga@test.com', self::SECRET);

        self::assertSame(42, $result['userId']);
        self::assertFalse($result['expired']);
    }

    public function testVerifyJwtExpired(): void
    {
        $token = $this->generateToken(['exp' => time() - 100]);
        $result = ApiAuthController::verifyJwt($token, 'orga@test.com', self::SECRET);

        self::assertSame(42, $result['userId']);
        self::assertTrue($result['expired']);
    }

    public function testVerifyJwtInvalidSignature(): void
    {
        $token = $this->generateToken();
        $result = ApiAuthController::verifyJwt($token, 'orga@test.com', 'wrong_secret');

        self::assertNull($result['userId']);
        self::assertFalse($result['expired']);
    }

    public function testVerifyJwtWrongEmail(): void
    {
        $token = $this->generateToken();
        $result = ApiAuthController::verifyJwt($token, 'other@test.com', self::SECRET);

        self::assertNull($result['userId']);
        self::assertFalse($result['expired']);
    }

    public function testVerifyJwtMalformedToken(): void
    {
        $result = ApiAuthController::verifyJwt('not.a.valid.token.at.all', 'orga@test.com', self::SECRET);
        self::assertNull($result['userId']);
    }

    public function testVerifyJwtTooFewParts(): void
    {
        $result = ApiAuthController::verifyJwt('only.two', 'orga@test.com', self::SECRET);
        self::assertNull($result['userId']);
    }

    public function testVerifyJwtEmptyPayload(): void
    {
        $header = $this->base64UrlEncode(json_encode(['alg' => 'HS256']));
        $payloadB64 = $this->base64UrlEncode('');
        $signature = $this->base64UrlEncode(hash_hmac('sha256', $header.'.'.$payloadB64, self::SECRET, true));

        $result = ApiAuthController::verifyJwt($header.'.'.$payloadB64.'.'.$signature, 'orga@test.com', self::SECRET);
        self::assertNull($result['userId']);
    }
}
