<?php

declare(strict_types=1);

namespace Tests\Integration;

use Tests\Support\QdbTestCase;

final class TokenTest extends QdbTestCase
{
    public function testTokenAddGetRevoke(): void
    {
        $token = bin2hex(random_bytes(32));
        $f = $this->fixture();
        token_add($token, 3600, [
            'userID'   => $f->adminUserId,
            'role'     => 'admin',
            'entityID' => 'ent',
        ]);
        $rec = token_get_record($token);
        $this->assertNotNull($rec);
        $this->assertSame('admin', $rec['role']);
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $stored = $pdo->query('SELECT token FROM session LIMIT 1')->fetchColumn();
        qdb_discard($tmpDb, $lockFp);
        $this->assertSame(token_storage_key($token), $stored);
        $this->assertNotSame($token, $stored);

        token_revoke($token);
        $this->assertNull(token_get_record($token));
    }

    public function testRevokeAllForUser(): void
    {
        $f = $this->fixture();
        $t1 = bin2hex(random_bytes(16));
        $t2 = bin2hex(random_bytes(16));
        token_add($t1, 3600, ['userID' => $f->supervisorUserId, 'role' => 'supervisor', 'entityID' => 'x']);
        token_add($t2, 3600, ['userID' => $f->supervisorUserId, 'role' => 'supervisor', 'entityID' => 'x']);
        $n = token_revoke_all_for_user($f->supervisorUserId);
        $this->assertGreaterThanOrEqual(2, $n);
        $this->assertNull(token_get_record($t1));
    }

    public function testTokenLookupRefreshesExpiry(): void
    {
        $token = bin2hex(random_bytes(32));
        $f = $this->fixture();
        token_add($token, 3600, [
            'userID'   => $f->adminUserId,
            'role'     => 'admin',
            'entityID' => 'ent',
        ]);

        [$pdo, $tmpDb, $lockFp] = qdb_open(true);
        $oldExpiry = time() + 60;
        $pdo->prepare('UPDATE session SET expiresAt = :exp WHERE token = :t')
            ->execute([':exp' => $oldExpiry, ':t' => token_storage_key($token)]);
        qdb_save($tmpDb, $lockFp);

        $rec = token_get_record($token);
        $this->assertNotNull($rec);
        $this->assertGreaterThan($oldExpiry + 3000, $rec['exp']);
    }
}
