package com.tomhempel.rbarometer.questionnaire

import com.tomhempel.rbarometer.data.ClientAnswersCache

/**
 * Loads prior answers from Room (or session cache) into the in-memory map before UI bind,
 * with types handlers expect (e.g. multi-checkbox as [List], not raw JSON strings).
 */
object SavedAnswerLoader {

    suspend fun loadInto(
        clientCode: String,
        questionnaireId: String,
        questions: List<QuestionItem>,
        answers: MutableMap<String, Any>,
        clearFirst: Boolean = true,
    ): Boolean {
        val code = clientCode.trim()
        if (code.isEmpty()) return false

        if (clearFirst) {
            answers.clear()
        }

        val rows = ClientAnswersCache.answersForQuestionnaire(code, questionnaireId)
        val allForClient = ClientAnswersCache.allForClient(code)

        var loaded = false
        for (row in rows) {
            if (row.answerValue.isBlank()) continue
            val key = AnswerKeyUtils.lookupKey(questionnaireId, row.questionId)
            answers[key] = row.answerValue
            loaded = true
        }

        for (question in questions) {
            if (question !is QuestionItem.GlassScaleQuestion) continue
            for (symptomKey in question.symptoms) {
                if (symptomKey.isBlank() || answers.containsKey(symptomKey)) continue
                val row = allForClient.find {
                    it.questionId == symptomKey ||
                        it.questionId == AnswerKeyUtils.roomQuestionId(questionnaireId, symptomKey)
                } ?: continue
                if (row.answerValue.isBlank()) continue
                answers[symptomKey] = row.answerValue
                loaded = true
            }
        }

        normalizeForHandlers(questions, answers)
        aliasAnswersByQuestionId(questions, answers)
        return loaded
    }

    /** Ensures handlers can resolve answers by [QuestionItem.id] as well as by question key. */
    private fun aliasAnswersByQuestionId(questions: List<QuestionItem>, answers: MutableMap<String, Any>) {
        for (question in questions) {
            val key = answerKeyFor(question) ?: continue
            val value = answers[key] ?: continue
            if (question.id.isNotBlank() && question.id != key && !answers.containsKey(question.id)) {
                answers[question.id] = value
            }
        }
    }

    /** Converts stored strings into types bind() reads without another DB round-trip. */
    fun normalizeForHandlers(questions: List<QuestionItem>, answers: MutableMap<String, Any>) {
        for (question in questions) {
            val key = answerKeyFor(question) ?: continue
            when (question) {
                is QuestionItem.MultiCheckboxQuestion -> {
                    val raw = answers[key] ?: continue
                    when (raw) {
                        is List<*> -> answers[key] = raw.mapNotNull { it?.toString() }.filter { it.isNotBlank() }
                        is String -> if (raw.isNotBlank()) {
                            answers[key] = parseMultiValue(raw)
                        }
                        else -> Unit
                    }
                }
                else -> Unit
            }
        }
    }

    private fun answerKeyFor(question: QuestionItem): String? = when (question) {
        is QuestionItem.RadioQuestion -> question.question ?: question.id
        is QuestionItem.MultiCheckboxQuestion -> question.question ?: question.id
        is QuestionItem.StringSpinnerQuestion -> question.question ?: question.id
        is QuestionItem.ValueSpinnerQuestion -> question.question ?: question.id
        is QuestionItem.FreeTextQuestion -> question.question ?: question.id
        is QuestionItem.DateSpinnerQuestion -> question.question ?: question.id
        is QuestionItem.SliderQuestion -> question.question ?: question.id
        else -> null
    }

    fun parseMultiValue(value: String): List<String> {
        val trimmed = value.trim()
        if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
            val inner = trimmed.substring(1, trimmed.length - 1)
            if (inner.isBlank()) return emptyList()
            return inner.split(",")
                .map { it.trim().trim('"', '\'') }
                .filter { it.isNotEmpty() }
        }
        val separator = when {
            trimmed.contains(",") -> ","
            trimmed.contains(";") -> ";"
            else -> null
        }
        return if (separator != null) {
            trimmed.split(separator)
                .map { it.trim().trim('"', '\'') }
                .filter { it.isNotEmpty() }
        } else {
            listOf(trimmed.trim().trim('"', '\''))
        }
    }
}
