<?php
/**
 * Mobile app answer ingest/export helpers (submit payload ↔ client_answer rows).
 */

/** Encode multi-select keys the same way the Android app stores them locally. */
function qdb_encode_multi_check_values(array $keys): string {
    $clean = [];
    foreach ($keys as $k) {
        $k = trim((string)$k);
        if ($k !== '') {
            $clean[$k] = true;
        }
    }
    return json_encode(array_keys($clean), JSON_UNESCAPED_UNICODE);
}

/** @return list<string> */
function qdb_decode_multi_check_values(?string $raw): array {
    if ($raw === null || trim($raw) === '') {
        return [];
    }
    $trimmed = trim($raw);
    if ($trimmed[0] === '[') {
        $decoded = json_decode($trimmed, true);
        if (is_array($decoded)) {
            $out = [];
            foreach ($decoded as $v) {
                $s = trim((string)$v);
                if ($s !== '') {
                    $out[] = $s;
                }
            }
            return $out;
        }
    }
    $sep = str_contains($trimmed, ',') ? ',' : (str_contains($trimmed, ';') ? ';' : null);
    if ($sep !== null) {
        $parts = [];
        foreach (explode($sep, $trimmed) as $p) {
            $s = trim($p, " \t\n\r\0\x0B\"'");
            if ($s !== '') {
                $parts[] = $s;
            }
        }
        return $parts;
    }
    return [$trimmed];
}

/**
 * Build glass-scale symptom JSON from the current submit only (no merge with prior rows).
 *
 * @param array<string, string> $symptomLabels symptom key => selected label
 */
function qdb_build_glass_symptom_json(array $symptomLabels): ?string {
    $data = [];
    foreach ($symptomLabels as $key => $label) {
        $k = trim((string)$key);
        $v = trim((string)$label);
        if ($k !== '' && $v !== '') {
            $data[$k] = $v;
        }
    }
    if ($data === []) {
        return null;
    }
    return json_encode($data, JSON_UNESCAPED_UNICODE);
}

/**
 * Group raw POST answer rows by question short id; merge multi_check option keys.
 *
 * @param array<string, string> $shortIdToType question localId => layout type
 * @return list<array<string, mixed>>
 */
function qdb_group_app_submit_answers(array $answers, array $shortIdToType, array $symptomParentMap): array {
    $grouped = [];
    $order = [];

    foreach ($answers as $a) {
        if (!is_array($a)) {
            continue;
        }
        $shortId = trim($a['questionID'] ?? '');
        if ($shortId === '') {
            continue;
        }

        if (isset($symptomParentMap[$shortId])) {
            $order[] = $shortId;
            $grouped[$shortId] = $a;
            continue;
        }

        $type = $shortIdToType[$shortId] ?? '';
        if ($type === 'multi_check_box_question') {
            if (!isset($grouped[$shortId])) {
                $order[] = $shortId;
                $grouped[$shortId] = [
                    'questionID'      => $shortId,
                    'multiOptionKeys' => [],
                    'answeredAt'      => $a['answeredAt'] ?? null,
                ];
            }
            $key = trim((string)($a['answerOptionKey'] ?? ''));
            if ($key !== '') {
                $grouped[$shortId]['multiOptionKeys'][$key] = true;
            }
            continue;
        }

        $order[] = $shortId;
        $grouped[$shortId] = $a;
    }

    $out = [];
    foreach ($order as $shortId) {
        $row = $grouped[$shortId];
        if (!empty($row['multiOptionKeys'])) {
            $keys = array_keys($row['multiOptionKeys']);
            $out[] = [
                'questionID'    => $shortId,
                'freeTextValue' => qdb_encode_multi_check_values($keys),
                'answeredAt'    => $row['answeredAt'] ?? null,
            ];
        } else {
            unset($row['multiOptionKeys']);
            $out[] = $row;
        }
    }
    return $out;
}

/**
 * Export one client's answers for one questionnaire into app submit shape.
 *
 * @return array{answers: list<array<string, mixed>>, sumPoints: int, completedAt: ?int}
 */
function qdb_export_app_questionnaire_answers(
    PDO $pdo,
    string $clientCode,
    string $qnID
): array {
    $qStmt = $pdo->prepare(
        "SELECT questionID, type, configJson FROM question WHERE questionnaireID = :qn"
    );
    $qStmt->execute([':qn' => $qnID]);
    $shortToFull = [];
    $fullToShort = [];
    $fullToType = [];
    $symptomParentMap = qdb_glass_symptom_parent_map($pdo, $qnID);

    foreach ($qStmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
        $full = $row['questionID'];
        $parts = explode('__', $full);
        $short = end($parts);
        $shortToFull[$short] = $full;
        $fullToShort[$full] = $short;
        $fullToType[$full] = $row['type'] ?? '';
    }

    $aoStmt = $pdo->prepare("
        SELECT ao.answerOptionID, ao.questionID, ao.defaultText
        FROM answer_option ao
        JOIN question q ON q.questionID = ao.questionID
        WHERE q.questionnaireID = :qn
    ");
    $aoStmt->execute([':qn' => $qnID]);
    $optionIdToKey = [];
    foreach ($aoStmt->fetchAll(PDO::FETCH_ASSOC) as $ao) {
        $optionIdToKey[$ao['answerOptionID']] = $ao['defaultText'];
    }

    $caStmt = $pdo->prepare("
        SELECT ca.questionID, ca.answerOptionID, ca.freeTextValue, ca.numericValue, ca.answeredAt
        FROM client_answer ca
        JOIN question q ON q.questionID = ca.questionID
        WHERE ca.clientCode = :cc AND q.questionnaireID = :qn
    ");
    $caStmt->execute([':cc' => $clientCode, ':qn' => $qnID]);
    $rows = $caStmt->fetchAll(PDO::FETCH_ASSOC);

    $export = [];
    foreach ($rows as $row) {
        $fullQid = $row['questionID'];
        $shortId = $fullToShort[$fullQid] ?? '';
        if ($shortId === '') {
            continue;
        }
        $type = $fullToType[$fullQid] ?? '';

        if ($type === 'glass_scale_question' && ($row['freeTextValue'] ?? '') !== '') {
            $decoded = json_decode($row['freeTextValue'], true);
            if (is_array($decoded)) {
                foreach ($decoded as $symptomKey => $label) {
                    $sk = trim((string)$symptomKey);
                    $lab = trim((string)$label);
                    if ($sk !== '' && $lab !== '') {
                        $export[] = [
                            'questionID'      => $sk,
                            'answerOptionKey' => $lab,
                        ];
                    }
                }
            }
            continue;
        }

        if ($type === 'multi_check_box_question') {
            foreach (qdb_decode_multi_check_values($row['freeTextValue'] ?? null) as $key) {
                $export[] = [
                    'questionID'      => $shortId,
                    'answerOptionKey' => $key,
                ];
            }
            if ($export === [] && !empty($row['answerOptionID']) && isset($optionIdToKey[$row['answerOptionID']])) {
                $export[] = [
                    'questionID'      => $shortId,
                    'answerOptionKey' => $optionIdToKey[$row['answerOptionID']],
                ];
            }
            continue;
        }

        $entry = ['questionID' => $shortId];
        if (!empty($row['answerOptionID']) && isset($optionIdToKey[$row['answerOptionID']])) {
            $entry['answerOptionKey'] = $optionIdToKey[$row['answerOptionID']];
        }
        if (isset($row['freeTextValue']) && $row['freeTextValue'] !== null && $row['freeTextValue'] !== '') {
            $entry['freeTextValue'] = $row['freeTextValue'];
        }
        if (isset($row['numericValue']) && $row['numericValue'] !== null && $row['numericValue'] !== '') {
            $entry['numericValue'] = (float)$row['numericValue'];
        }
        if (!empty($row['answeredAt'])) {
            $entry['answeredAt'] = (int)$row['answeredAt'];
        }
        $export[] = $entry;
    }

    $cq = $pdo->prepare(
        "SELECT sumPoints, completedAt FROM completed_questionnaire
         WHERE clientCode = :cc AND questionnaireID = :qn"
    );
    $cq->execute([':cc' => $clientCode, ':qn' => $qnID]);
    $meta = $cq->fetch(PDO::FETCH_ASSOC) ?: [];

    return [
        'answers'     => $export,
        'sumPoints'   => isset($meta['sumPoints']) ? (int)$meta['sumPoints'] : 0,
        'completedAt' => isset($meta['completedAt']) ? (int)$meta['completedAt'] : null,
    ];
}

/**
 * Export all completed questionnaires for a client (coach RBAC must be applied by caller).
 *
 * @return list<array<string, mixed>>
 */
function qdb_export_app_client_answers_bundle(PDO $pdo, string $clientCode): array {
    $stmt = $pdo->prepare(
        "SELECT questionnaireID FROM completed_questionnaire WHERE clientCode = :cc"
    );
    $stmt->execute([':cc' => $clientCode]);
    $items = [];
    foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $qnID) {
        $block = qdb_export_app_questionnaire_answers($pdo, $clientCode, $qnID);
        $items[] = [
            'questionnaireID' => $qnID,
            'completedAt'     => $block['completedAt'],
            'sumPoints'       => $block['sumPoints'],
            'answers'         => $block['answers'],
        ];
    }
    return $items;
}

/**
 * Bulk export: all coach-assigned clients with full answer bundles (caller applies RBAC).
 *
 * @return list<array{clientCode: string, questionnaires: list<array<string, mixed>>}>
 */
function qdb_export_app_bulk_answers_for_coach(PDO $pdo, array $tokenRec): array {
    if (($tokenRec['role'] ?? '') !== 'coach') {
        return [];
    }
    $coachID = trim((string)($tokenRec['entityID'] ?? ''));
    if ($coachID === '') {
        return [];
    }
    $stmt = $pdo->prepare(
        'SELECT clientCode FROM client
         WHERE coachID = :cid AND COALESCE(archived, 0) = 0
         ORDER BY clientCode'
    );
    $stmt->execute([':cid' => $coachID]);
    $out = [];
    foreach ($stmt->fetchAll(PDO::FETCH_COLUMN) as $clientCode) {
        $out[] = [
            'clientCode'     => $clientCode,
            'questionnaires' => qdb_export_app_client_answers_bundle($pdo, (string)$clientCode),
        ];
    }
    return $out;
}
