package com.tomhempel.rbarometer.questionnaire.handlers

import android.content.Context
import android.util.TypedValue
import android.view.View
import android.widget.*
import androidx.core.widget.TextViewCompat
import kotlinx.coroutines.*
import com.tomhempel.rbarometer.questionnaire.GlobalValues
import com.tomhempel.rbarometer.LanguageManager
import com.tomhempel.rbarometer.data.AnswerRepository
import com.tomhempel.rbarometer.questionnaire.QuestionFlowResolver
import com.tomhempel.rbarometer.questionnaire.QuestionHandler
import com.tomhempel.rbarometer.questionnaire.QuestionItem
import com.tomhempel.rbarometer.R
import com.tomhempel.rbarometer.utils.ViewUtils

/*
Zweck:
- Steuert eine Frage mit mehreren auswählbaren Antwortoptionen (Checkboxen).
*/

class HandlerMultiCheckboxQuestion(
    private val context: Context,
    private val answers: MutableMap<String, Any>,
    private val languageID: String,
    private val goToNextQuestion: () -> Unit,
    private val goToPreviousQuestion: () -> Unit,
    private val goToQuestionById: (String) -> Unit,
    private val showToast: (String) -> Unit,
    private val questionnaireMeta: String //
) : QuestionHandler {

    private lateinit var layout: View
    private lateinit var question: QuestionItem.MultiCheckboxQuestion

    override fun bind(layout: View, question: QuestionItem) {
        this.layout = layout
        this.question = question as QuestionItem.MultiCheckboxQuestion

        val container = layout.findViewById<LinearLayout>(R.id.CheckboxContainer)
        val questionTitle = layout.findViewById<TextView>(R.id.question)
        val questionTextView = layout.findViewById<TextView>(R.id.textView)

        questionTextView.text = this.question.textKey?.let { LanguageManager.getText(languageID, it) } ?: ""
        questionTitle.text = this.question.question?.let { LanguageManager.getText(languageID, it) } ?: ""

        // Textgrößen pro Bildschirmhöhe (wie bei deinen anderen Handlern)
        ViewUtils.setTextSizePercentOfScreenHeight(questionTextView, 0.03f)
        ViewUtils.setTextSizePercentOfScreenHeight(questionTitle,    0.03f)

        container.removeAllViews()

        val answerMapKey = question.question ?: (question.id ?: "")
        val selectedKeys = selectedKeysFromAnswers(answerMapKey)

        // Checkbox-Schrift & Zeilenhöhe dynamisch ableiten (kein Abschneiden)
        val dm = layout.resources.displayMetrics
        val scale = ViewUtils.spScale(dm)
        val cbTextSp = (dm.heightPixels * ViewUtils.scaledScreenHeightPercent(0.025f)) / scale
        val cbTextPx = cbTextSp * scale
        val cbPadV   = (cbTextPx * 0.40f).toInt()
        val cbMinH   = (cbTextPx * 1.60f + 2 * cbPadV).toInt()

        (this.question.options ?: emptyList()).forEach { option ->
            val checkBox = CheckBox(context).apply {
                text = LanguageManager.getText(languageID, option.key)
                tag = option.key
                isChecked = selectedKeys.contains(option.key)

                // Textgröße prozentual & Zeilenhöhe/Padding für Lesbarkeit
                TextViewCompat.setAutoSizeTextTypeWithDefaults(this, TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE)
                setTextSize(TypedValue.COMPLEX_UNIT_SP, cbTextSp)
                includeFontPadding = true
                setPadding(paddingLeft, cbPadV, paddingRight, cbPadV)
                minHeight = cbMinH

                layoutParams = LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    val scale = context.resources.displayMetrics.density
                    val marginBottom = (16 * scale + 0.5f).toInt()
                    setMargins(0, 0, 0, marginBottom)
                }
            }
            container.addView(checkBox)
        }

        if (answerMapKey.isNotBlank() && !answers.containsKey(answerMapKey)) {
            CoroutineScope(Dispatchers.IO).launch {
                try {
                    val clientCode = GlobalValues.LAST_CLIENT_CODE
                    if (clientCode.isNullOrBlank()) return@launch

                    val allAnswersForClient = AnswerRepository.getAnswersForClient(clientCode)
                    val myQuestionId = questionnaireMeta + "-" + question.question
                    val dbAnswer = allAnswersForClient.find { it.questionId == myQuestionId }?.answerValue

                    if (!dbAnswer.isNullOrBlank()) {
                        val parsed = parseMultiAnswer(dbAnswer)

                        withContext(Dispatchers.Main) {
                            // UI: Checkboxen setzen
                            for (i in 0 until container.childCount) {
                                val cb = container.getChildAt(i) as? CheckBox ?: continue
                                cb.isChecked = parsed.contains(cb.tag.toString())
                            }

                            // answers-Map aktualisieren
                            answers[answerMapKey] = parsed.toList()
                        }
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }

        layout.findViewById<Button>(R.id.Qnext).setOnClickListener {
            if (validate()) {
                saveAnswer()
                val selected = collectSelectedKeys()
                val nextId = QuestionFlowResolver.nextQuestionIdForMultiCheckbox(question, selected)
                if (!nextId.isNullOrEmpty()) {
                    goToQuestionById(nextId)
                } else {
                    goToNextQuestion()
                }
            } else {
                val msgKey = if (question.minSelection == 1) {
                    "select_at_least_one_answer"
                } else {
                    "select_at_least_minimum"
                }
                val errorMessage = LanguageManager.getTextFormatted(languageID, msgKey, "choose_more_elements")
                showToast(errorMessage)
            }
        }

        layout.findViewById<Button>(R.id.Qprev).setOnClickListener {
            goToPreviousQuestion()
        }
    }

    override fun validate(): Boolean {
        val container = layout.findViewById<LinearLayout>(R.id.CheckboxContainer)
        var selectedCount = 0
        for (i in 0 until container.childCount) {
            val checkBox = container.getChildAt(i) as? CheckBox ?: continue
            if (checkBox.isChecked) selectedCount++
        }
        return selectedCount >= question.minSelection
    }

    private fun collectSelectedKeys(): Set<String> {
        val container = layout.findViewById<LinearLayout>(R.id.CheckboxContainer)
        val selectedKeys = mutableSetOf<String>()
        for (i in 0 until container.childCount) {
            val checkBox = container.getChildAt(i) as? CheckBox ?: continue
            if (checkBox.isChecked) selectedKeys.add(checkBox.tag.toString())
        }
        return selectedKeys
    }

    override fun saveAnswer() {
        val selectedKeys = collectSelectedKeys().toList()
        question.question?.let { questionKey ->
            answers[questionKey] = selectedKeys
        }
    }

    private fun selectedKeysFromAnswers(answerMapKey: String): Set<String> {
        if (answerMapKey.isBlank()) return emptySet()
        return when (val stored = answers[answerMapKey]) {
            is Collection<*> -> stored.mapNotNull { it?.toString() }.filter { it.isNotBlank() }.toSet()
            is String -> if (stored.isNotBlank()) parseMultiAnswer(stored) else emptySet()
            else -> emptySet()
        }
    }

    private fun parseMultiAnswer(dbAnswer: String): Set<String> {
        val trimmed = dbAnswer.trim()
        if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
            val inner = trimmed.substring(1, trimmed.length - 1)
            if (inner.isBlank()) return emptySet()
            return inner.split(",")
                .map { it.trim().trim('"', '\'') }
                .filter { it.isNotEmpty() }
                .toSet()
        }

        val separator = when {
            trimmed.contains(",") -> ","
            trimmed.contains(";") -> ";"
            else -> null
        }

        return if (separator != null) {
            trimmed.split(separator)
                .map { it.trim().trim('"', '\'') }
                .filter { it.isNotEmpty() }
                .toSet()
        } else {
            setOf(trimmed.trim().trim('"', '\''))
        }
    }

}
