<?php

declare(strict_types=1);

namespace Tests\Integration;

use Tests\Support\DatabaseSeeder;
use Tests\Support\QdbTestCase;

final class SecurityPathsTest extends QdbTestCase
{
    public function testExpiredTokenRejected(): void
    {
        $token = bin2hex(random_bytes(32));
        $f = $this->fixture();
        [$pdo, $tmpDb, $lockFp] = qdb_open(true);
        $pdo->prepare(
            'INSERT INTO session (token, userID, role, entityID, createdAt, expiresAt, temp)
             VALUES (:t, :uid, :role, :eid, :ca, :ea, 0)'
        )->execute([
            ':t'    => token_storage_key($token),
            ':uid'  => $f->adminUserId,
            ':role' => 'admin',
            ':eid'  => 'ent',
            ':ca'   => time() - 7200,
            ':ea'   => time() - 3600,
        ]);
        qdb_save($tmpDb, $lockFp);

        $res = $this->api()->withToken($token, 'GET', 'session');
        $this->assertApiError($res, 'UNAUTHORIZED', 401);
    }

    public function testInvalidBearerRejected(): void
    {
        $res = $this->api()->request('GET', 'session', null, [
            'Authorization' => 'Bearer not-a-valid-session-token',
            'X-QDB-Client'  => 'web',
        ]);
        $this->assertApiError($res, 'UNAUTHORIZED', 401);
    }

    public function testAppSubmitRequiresEncryptedBody(): void
    {
        $login = $this->api()->loginMobileAndGetToken(
            DatabaseSeeder::COACH_USERNAME,
            DatabaseSeeder::PASSWORD
        );
        $f = $this->fixture();
        $res = $this->api()->withMobileToken($login['token'], 'POST', 'app_questionnaires', [
            'questionnaireID' => $f->questionnaireId,
            'clientCode'      => $f->clientCode,
            'answers'         => [],
        ]);
        $this->assertApiError($res, 'ENCRYPTION_REQUIRED', 400);
    }

    public function testAppSubmitValidationFailure(): void
    {
        $login = $this->api()->loginMobileAndGetToken(
            DatabaseSeeder::COACH_USERNAME,
            DatabaseSeeder::PASSWORD
        );
        $f = $this->fixture();
        $res = $this->api()->encryptedPost($login['token'], 'app_questionnaires', [
            'questionnaireID' => $f->questionnaireId,
            'clientCode'      => $f->clientCode,
            'answers'         => [],
        ]);
        $this->assertApiError($res, 'VALIDATION_FAILED', 400);
        $this->assertNotEmpty($res['error']['details']['errors'] ?? []);
    }

    public function testCoachCannotSubmitForUnknownClient(): void
    {
        $login = $this->api()->loginMobileAndGetToken(
            DatabaseSeeder::COACH_USERNAME,
            DatabaseSeeder::PASSWORD
        );
        $f = $this->fixture();
        $res = $this->api()->encryptedPost($login['token'], 'app_questionnaires', [
            'questionnaireID' => $f->questionnaireId,
            'clientCode'      => 'CLIENT-DOES-NOT-EXIST',
            'answers'         => [
                ['questionID' => $f->questionShortId, 'answerOptionKey' => 'yes'],
            ],
        ]);
        $this->assertApiError($res, 'NOT_FOUND', 404);
    }
}
