<?php

declare(strict_types=1);

namespace Tests\Unit;

use Tests\Support\QdbTestCase;

final class AppSubmitValidateTest extends QdbTestCase
{
    public function testEmptyAnswersRejected(): void
    {
        require_once dirname(__DIR__, 2) . '/lib/app_submit_validate.php';
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $f = $this->fixture();
        $errors = qdb_validate_app_submit_payload($pdo, $f->questionnaireId, [], [], [], [], []);
        qdb_discard($tmpDb, $lockFp);
        $this->assertNotEmpty($errors);
        $this->assertSame('ANSWERS_REQUIRED', $errors[0]['code']);
    }

    public function testUnknownQuestionRejected(): void
    {
        require_once dirname(__DIR__, 2) . '/lib/app_submit_validate.php';
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $f = $this->fixture();
        $errors = qdb_validate_app_submit_payload(
            $pdo,
            $f->questionnaireId,
            [['questionID' => 'nope', 'answerOptionKey' => 'x']],
            [],
            [],
            [],
            []
        );
        qdb_discard($tmpDb, $lockFp);
        $this->assertSame('UNKNOWN_QUESTION', $errors[0]['code'] ?? '');
    }

    public function testUnknownQuestionAllowedInLegacyManifest(): void
    {
        require_once dirname(__DIR__, 2) . '/lib/app_submit_validate.php';
        require_once dirname(__DIR__, 2) . '/lib/questionnaire_structure.php';
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $f = $this->fixture();
        $manifest = qdb_build_structure_manifest($pdo, $f->questionnaireId, true);
        $maps = qdb_submit_maps_from_manifest($pdo, $f->questionnaireId, $manifest);
        $errors = qdb_validate_app_submit_payload(
            $pdo,
            $f->questionnaireId,
            [['questionID' => $f->questionShortId, 'answerOptionKey' => 'yes']],
            $maps['shortIdMap'],
            $maps['shortIdToType'],
            $maps['symptomParentMap'],
            $maps['optionMap'],
            $manifest
        );
        qdb_discard($tmpDb, $lockFp);
        $this->assertSame([], $errors);
    }

    public function testValidSingleChoiceWithOptionKeyPasses(): void
    {
        require_once dirname(__DIR__, 2) . '/lib/app_submit_validate.php';
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $f = $this->fixture();
        $shortMap = [$f->questionShortId => $f->questionId];
        $typeMap = [$f->questionShortId => 'single_choice_question'];
        $optMap = [
            $f->questionId => [
                'yes' => ['answerOptionID' => $f->optionId, 'points' => 0],
            ],
        ];
        $errors = qdb_validate_app_submit_payload(
            $pdo,
            $f->questionnaireId,
            [['questionID' => $f->questionShortId, 'answerOptionKey' => 'yes']],
            $shortMap,
            $typeMap,
            [],
            $optMap,
        );
        qdb_discard($tmpDb, $lockFp);
        $this->assertSame([], $errors);
    }

    public function testMultiCheckRequiresSelection(): void
    {
        require_once dirname(__DIR__, 2) . '/lib/app_submit_validate.php';
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $f = $this->fixture();
        $shortMap = [$f->multiCheckShortId => $f->multiCheckQuestionId];
        $typeMap = [$f->multiCheckShortId => 'multi_check_box_question'];
        $errors = qdb_validate_app_submit_payload(
            $pdo,
            $f->questionnaireId,
            [['questionID' => $f->multiCheckShortId, 'freeTextValue' => '']],
            $shortMap,
            $typeMap,
            [],
            [],
        );
        qdb_discard($tmpDb, $lockFp);
        $this->assertSame('EMPTY_ANSWER', $errors[0]['code'] ?? '');
    }

    public function testInvalidOptionKeyRejected(): void
    {
        require_once dirname(__DIR__, 2) . '/lib/app_submit_validate.php';
        [$pdo, $tmpDb, $lockFp] = qdb_open(false);
        $f = $this->fixture();
        $shortMap = [$f->questionShortId => $f->questionId];
        $typeMap = [$f->questionShortId => 'single_choice_question'];
        $optMap = [
            $f->questionId => [
                'yes' => ['answerOptionID' => $f->optionId, 'points' => 0],
            ],
        ];
        $errors = qdb_validate_app_submit_payload(
            $pdo,
            $f->questionnaireId,
            [['questionID' => $f->questionShortId, 'answerOptionKey' => 'No']],
            $shortMap,
            $typeMap,
            [],
            $optMap,
        );
        qdb_discard($tmpDb, $lockFp);
        $this->assertSame('INVALID_OPTION', $errors[0]['code'] ?? '');
    }
}
