package app.closer.data.questions

import android.util.Log
import app.closer.BuildConfig
import app.closer.domain.model.*
import org.json.JSONArray
import org.json.JSONObject

/**
 * Parses a JSON file containing question data in the v2 schema format.
 *
 * Expected JSON structure:
 * {
 *   "category": { ... },
 *   "questions": [
 *     {
 *       "id": "...",
 *       "category_id": "...",
 *       "type": "written|single_choice|multi_choice|scale|this_or_that",
 *       "text": "...",
 *       "depth": 1-5,
 *       "access": "free|premium",
 *       "tags": [...],
 *       "answer_config": { ... }
 *     }
 *   ]
 * }
 */
object QuestionJsonParser {

    private const val TAG = "QuestionJsonParser"

    data class ParsedQuestionBundle(
        val category: QuestionCategory,
        val questions: List<Question>
    )

    fun parseFromFile(jsonFilePath: String): ParsedQuestionBundle? {
        val jsonContent = try {
            java.io.File(jsonFilePath).readText()
        } catch (e: Exception) {
            if (BuildConfig.DEBUG) {
                Log.e(TAG, "Failed to read JSON file: ${e.message}")
            }
            return null
        }

        return parseFromJsonString(jsonContent)
    }

    fun parseFromJsonString(jsonString: String): ParsedQuestionBundle? {
        return try {
            val root = JSONObject(jsonString)
            val categoryObj = root.getJSONObject("category")
            val questionsArray = root.getJSONArray("questions")

            val category = parseCategory(categoryObj)
            val questions = mutableListOf<Question>()

            for (i in 0 until questionsArray.length()) {
                val questionObj = questionsArray.getJSONObject(i)
                questionObj?.let { q ->
                    questions.add(parseQuestion(q, category.id))
                }
            }

            ParsedQuestionBundle(category, questions)
        } catch (e: Exception) {
            if (BuildConfig.DEBUG) {
                Log.e(TAG, "Failed to parse JSON: ${e.message}")
            }
            null
        }
    }

    private fun parseCategory(obj: JSONObject): QuestionCategory {
        return QuestionCategory(
            id = obj.optString("id", ""),
            displayName = obj.optString("display_name", ""),
            description = obj.optString("description", ""),
            access = obj.optString("access", "free"),
            iconName = obj.optString("icon_name", "message")
        )
    }

    private fun parseQuestion(obj: JSONObject, categoryId: String): Question {
        val type = obj.optString("type", "written")
        val tags = obj.optJSONArray("tags")?.let { arr ->
            mutableListOf<String>().apply {
                for (i in 0 until arr.length()) {
                    add(arr.optString(i))
                }
            }.toList()
        } ?: emptyList()

        val answerConfig = parseAnswerConfig(obj, type)

        return Question(
            id = obj.optString("id", ""),
            text = obj.optString("text", ""),
            category = categoryId,
            depthLevel = obj.optInt("depth", 1),
            isPremium = obj.optString("access", "free") == "premium",
            type = type,
            tags = tags,
            answerConfig = answerConfig
        )
    }

    private fun parseAnswerConfig(obj: JSONObject, type: String): AnswerConfig? {
        val answerConfigObj = obj.optJSONObject("answer_config")
        if (answerConfigObj == null) return null

        return when (type) {
            "written" -> {
                WrittenAnswerConfigImpl(
                    config = WrittenAnswerConfig(
                        minLength = answerConfigObj.optInt("min_length", 1),
                        maxLength = answerConfigObj.optInt("max_length", 1000),
                        placeholder = answerConfigObj.optString("placeholder", "Write your answer...")
                    )
                )
            }
            "single_choice" -> {
                val options = mutableListOf<ChoiceOption>()
                val optionsArray = obj.optJSONArray("options")
                if (optionsArray != null) {
                    for (i in 0 until optionsArray.length()) {
                        val opt = optionsArray.optJSONObject(i)
                        opt?.let { o ->
                            options.add(ChoiceOption(
                                id = o.optString("id", ""),
                                text = o.optString("text", "")
                            ))
                        }
                    }
                }
                ChoiceAnswerConfigImpl(
                    config = ChoiceAnswerConfig(options = options.toList())
                )
            }
            "scale" -> {
                ScaleAnswerConfigImpl(
                    config = ScaleAnswerConfig(
                        minScale = answerConfigObj.optInt("min_scale", 1),
                        maxScale = answerConfigObj.optInt("max_scale", 5),
                        minLabel = answerConfigObj.optString("min_label", ""),
                        maxLabel = answerConfigObj.optString("max_label", ""),
                        scaleStep = answerConfigObj.optInt("scale_step", 1)
                    )
                )
            }
            "this_or_that" -> {
                val optionsArray = obj.optJSONArray("options")
                if (optionsArray?.length() == 2) {
                    val optA = optionsArray.optJSONObject(0)
                    val optB = optionsArray.optJSONObject(1)
                    ThisOrThatAnswerConfigImpl(
                        config = ThisOrThatAnswerConfig(
                            optionA = ChoiceOption(
                                id = optA?.optString("id", "") ?: "",
                                text = optA?.optString("text", "") ?: ""
                            ),
                            optionB = ChoiceOption(
                                id = optB?.optString("id", "") ?: "",
                                text = optB?.optString("text", "") ?: ""
                            )
                        )
                    )
                } else {
                    null
                }
            }
            "multi_choice" -> {
                val options = mutableListOf<ChoiceOption>()
                val optionsArray = obj.optJSONArray("options")
                if (optionsArray != null) {
                    for (i in 0 until optionsArray.length()) {
                        val opt = optionsArray.optJSONObject(i)
                        opt?.let { o ->
                            options.add(ChoiceOption(
                                id = o.optString("id", ""),
                                text = o.optString("text", "")
                            ))
                        }
                    }
                }
                ChoiceAnswerConfigImpl(
                    type = "multi_choice",
                    config = ChoiceAnswerConfig(
                        options = options.toList(),
                        maxSelections = answerConfigObj.optInt("max_selections", 0)
                    )
                )
            }
            else -> null
        }
    }
}
