package app.closer.data.local.mapper

import app.closer.data.local.entity.QuestionEntity
import app.closer.data.local.entity.CategoryEntity
import app.closer.domain.model.ChoiceAnswerConfig
import app.closer.domain.model.ChoiceAnswerConfigImpl
import app.closer.domain.model.ChoiceOption
import app.closer.domain.model.Question
import app.closer.domain.model.QuestionCategory
import app.closer.domain.model.ScaleAnswerConfig
import app.closer.domain.model.ScaleAnswerConfigImpl
import app.closer.domain.model.ThisOrThatAnswerConfig
import app.closer.domain.model.ThisOrThatAnswerConfigImpl
import app.closer.domain.model.WrittenAnswerConfig
import app.closer.domain.model.WrittenAnswerConfigImpl
import org.json.JSONArray
import org.json.JSONObject

fun QuestionEntity.toQuestion(): Question {
    return Question(
        id = id,
        text = text,
        category = categoryId,
        depthLevel = depthLevel,
        isPremium = isPremium,
        type = type,
        tags = parseTags(tags),
        answerConfig = parseAnswerConfig(answerConfig, type),
        packId = packId,
        createdAt = createdAt,
        status = status,
        sex = sex
    )
}

fun CategoryEntity.toQuestionCategory(): QuestionCategory {
    return QuestionCategory(
        id = id,
        displayName = displayName,
        description = description,
        access = access,
        iconName = iconName
    )
}

private fun parseTags(raw: String): List<String> = try {
    val arr = JSONArray(raw)
    (0 until arr.length()).map { arr.getString(it) }
} catch (e: Exception) {
    emptyList()
}

private fun parseAnswerConfig(raw: String, questionType: String) = try {
    val json = JSONObject(raw)
    val configObj = json.optJSONObject("config")
    when (questionType) {
        "written" -> WrittenAnswerConfigImpl(
            config = WrittenAnswerConfig(
                minLength = configObj?.optInt("minLength", 1) ?: 1,
                maxLength = configObj?.optInt("maxLength", 1000) ?: 1000,
                placeholder = configObj?.optString("placeholder", "Write your answer...") ?: "Write your answer..."
            )
        )
        "single_choice", "multi_choice" -> {
            val optionsArr = configObj?.optJSONArray("options")
            val options = parseOptions(optionsArr)
            val maxSel = if (questionType == "multi_choice") configObj?.optInt("maxSelections", 0) ?: 0 else 0
            ChoiceAnswerConfigImpl(type = questionType, config = ChoiceAnswerConfig(options = options, maxSelections = maxSel))
        }
        "scale" -> ScaleAnswerConfigImpl(
            config = ScaleAnswerConfig(
                minScale = configObj?.optInt("minScale", 1) ?: 1,
                maxScale = configObj?.optInt("maxScale", 5) ?: 5,
                minLabel = configObj?.optString("minLabel", "") ?: "",
                maxLabel = configObj?.optString("maxLabel", "") ?: "",
                scaleStep = configObj?.optInt("scaleStep", 1) ?: 1
            )
        )
        "this_or_that" -> {
            val optA = configObj?.optJSONObject("optionA")
            val optB = configObj?.optJSONObject("optionB")
            if (optA != null && optB != null) {
                ThisOrThatAnswerConfigImpl(
                    config = ThisOrThatAnswerConfig(
                        optionA = ChoiceOption(id = optA.optString("id", "a"), text = optA.optString("text", "")),
                        optionB = ChoiceOption(id = optB.optString("id", "b"), text = optB.optString("text", ""))
                    )
                )
            } else null
        }
        else -> null
    }
} catch (e: Exception) { null }

private fun parseOptions(arr: org.json.JSONArray?): List<ChoiceOption> {
    arr ?: return emptyList()
    return (0 until arr.length()).mapNotNull { i ->
        arr.optJSONObject(i)?.let { obj ->
            ChoiceOption(id = obj.optString("id", ""), text = obj.optString("text", ""))
        }
    }
}
