<?php

require_once __DIR__ . '/questionnaire_structure.php';

/**
 * Validate Android app questionnaire submit payloads before persisting answers.
 *
 * @param array<string, mixed>|null $manifest Structure manifest for legacy revision submits
 * @return list<array{questionID: string, code: string, message: string}>
 */
function qdb_validate_app_submit_payload(
    PDO $pdo,
    string $qnID,
    array $rawAnswers,
    array $shortIdMap,
    array $shortIdToType,
    array $symptomParentMap,
    array $optionMap,
    ?array $manifest = null
): array {
    $errors = [];

    if ($rawAnswers === []) {
        $errors[] = [
            'questionID' => '',
            'code'       => 'ANSWERS_REQUIRED',
            'message'    => 'At least one answer is required',
        ];
        return $errors;
    }

    foreach ($rawAnswers as $idx => $a) {
        if (!is_array($a)) {
            $errors[] = [
                'questionID' => '',
                'code'       => 'INVALID_ANSWER',
                'message'    => 'Answer at index ' . $idx . ' must be an object',
            ];
            continue;
        }
        $shortId = trim($a['questionID'] ?? '');
        if ($shortId === '') {
            $errors[] = [
                'questionID' => '',
                'code'       => 'MISSING_QUESTION_ID',
                'message'    => 'Each answer must include questionID',
            ];
            continue;
        }

        if (isset($symptomParentMap[$shortId])) {
            $label = trim((string)($a['answerOptionKey'] ?? $a['freeTextValue'] ?? ''));
            if ($label === '') {
                $errors[] = [
                    'questionID' => $shortId,
                    'code'       => 'EMPTY_ANSWER',
                    'message'    => 'Symptom selection is required',
                ];
            }
            continue;
        }

        if (!isset($shortIdMap[$shortId])) {
            $errors[] = [
                'questionID' => $shortId,
                'code'       => 'UNKNOWN_QUESTION',
                'message'    => 'Unknown question: ' . $shortId,
            ];
            continue;
        }

        $type = $shortIdToType[$shortId] ?? '';
        if (qdb_is_non_stored_answer_question_type($type)) {
            continue;
        }

        $fullQID = $shortIdMap[$shortId];
        $type    = $shortIdToType[$shortId] ?? '';
        $optKey  = $a['answerOptionKey'] ?? null;
        $free    = isset($a['freeTextValue']) ? trim((string)$a['freeTextValue']) : '';
        $numeric = $a['numericValue'] ?? null;
        $hasNumeric = $numeric !== null && $numeric !== '';

        if ($type === 'multi_check_box_question') {
            if ($optKey !== null && trim((string)$optKey) !== '') {
                continue;
            }
            if ($free !== '') {
                continue;
            }
            $errors[] = [
                'questionID' => $shortId,
                'code'       => 'EMPTY_ANSWER',
                'message'    => 'Select at least one option',
            ];
            continue;
        }

        if ($optKey !== null && trim((string)$optKey) !== '') {
            $key = (string)$optKey;
            if (!isset($optionMap[$fullQID][$key])) {
                $errors[] = [
                    'questionID' => $shortId,
                    'code'       => 'INVALID_OPTION',
                    'message'    => 'Unknown option key: ' . $key,
                ];
            }
            continue;
        }

        if ($free !== '' || $hasNumeric) {
            continue;
        }

        $errors[] = [
            'questionID' => $shortId,
            'code'       => 'EMPTY_ANSWER',
            'message'    => 'Answer is empty',
        ];
    }

    if ($errors !== []) {
        return $errors;
    }

    require_once __DIR__ . '/app_answers.php';
    $grouped = qdb_group_app_submit_answers($rawAnswers, $shortIdToType, $symptomParentMap);
    $answeredShort = [];
    foreach ($grouped as $row) {
        $sid = trim($row['questionID'] ?? '');
        if ($sid !== '') {
            $answeredShort[$sid] = true;
        }
    }

    if ($manifest !== null) {
        return array_merge($errors, qdb_validate_required_answers_from_manifest($manifest, $answeredShort));
    }

    $qStmt = $pdo->prepare(
        'SELECT questionID, type, isRequired, configJson FROM question
         WHERE questionnaireID = :qn AND ' . qdb_active_questions_clause('question')
    );
    $qStmt->execute([':qn' => $qnID]);
    foreach ($qStmt->fetchAll(PDO::FETCH_ASSOC) as $qRow) {
        if ((int)($qRow['isRequired'] ?? 0) !== 1) {
            continue;
        }
        $fullId = $qRow['questionID'];
        $parts  = explode('__', $fullId);
        $short  = end($parts);
        $type   = $qRow['type'] ?? '';

        if ($type === 'glass_scale_question') {
            $cfg      = json_decode($qRow['configJson'] ?? '{}', true) ?: [];
            $symptoms = $cfg['symptoms'] ?? [];
            if (is_array($symptoms) && $symptoms !== []) {
                foreach ($symptoms as $symptomKey) {
                    $sk = trim((string)$symptomKey);
                    if ($sk === '') {
                        continue;
                    }
                    if (empty($answeredShort[$sk])) {
                        $errors[] = [
                            'questionID' => $sk,
                            'code'       => 'MISSING_ANSWER',
                            'message'    => 'Required symptom is not answered',
                        ];
                    }
                }
                continue;
            }
        }

        if (empty($answeredShort[$short])) {
            $errors[] = [
                'questionID' => $short,
                'code'       => 'MISSING_ANSWER',
                'message'    => 'Required question is not answered',
            ];
        }
    }

    return $errors;
}

/**
 * @return list<array{questionID: string, code: string, message: string}>
 */
function qdb_validate_required_answers_from_manifest(array $manifest, array $answeredShort): array {
    $errors = [];
    foreach ($manifest['questions'] ?? [] as $qEntry) {
        if (!is_array($qEntry) || empty($qEntry['isRequired'])) {
            continue;
        }
        $shortId = (string)($qEntry['shortId'] ?? '');
        $type = (string)($qEntry['type'] ?? '');
        if ($shortId === '') {
            continue;
        }
        if ($type === 'glass_scale_question') {
            foreach ($qEntry['symptoms'] ?? [] as $symptomKey) {
                $sk = trim((string)$symptomKey);
                if ($sk === '') {
                    continue;
                }
                if (empty($answeredShort[$sk])) {
                    $errors[] = [
                        'questionID' => $sk,
                        'code'       => 'MISSING_ANSWER',
                        'message'    => 'Required symptom is not answered',
                    ];
                }
            }
            continue;
        }
        if (empty($answeredShort[$shortId])) {
            $errors[] = [
                'questionID' => $shortId,
                'code'       => 'MISSING_ANSWER',
                'message'    => 'Required question is not answered',
            ];
        }
    }
    return $errors;
}
