package app.closer.ui.questions

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.domain.model.ChoiceAnswerConfigImpl
import app.closer.domain.repository.LocalAnswerRepository
import app.closer.domain.repository.QuestionRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

@HiltViewModel
class QuestionDetailViewModel @Inject constructor(
    private val repository: QuestionRepository,
    private val localAnswerRepository: LocalAnswerRepository,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val questionId: String = savedStateHandle["questionId"] ?: ""

    private val _uiState = MutableStateFlow(LocalQuestionUiState())
    val uiState: StateFlow<LocalQuestionUiState> = _uiState.asStateFlow()

    init {
        loadQuestion()
    }

    fun loadQuestion() {
        viewModelScope.launch {
            _uiState.value = LocalQuestionUiState(isLoading = true)
            try {
                val question = repository.getQuestionById(questionId)
                val answer = question?.let { localAnswerRepository.getAnswer(it.id) }
                _uiState.value = LocalQuestionUiState(
                    isLoading = false,
                    question = question,
                    pendingScaleValue = defaultScaleValue(question)
                ).withLocalAnswer(answer)
            } catch (e: Exception) {
                _uiState.value = LocalQuestionUiState(
                    isLoading = false,
                    error = e.message ?: "Could not load this question."
                )
            }
        }
    }

    fun updateWrittenText(text: String) {
        _uiState.update { it.copy(pendingWrittenText = text.take(MAX_ANSWER_LENGTH), submitted = false) }
    }

    fun toggleOption(optionId: String) {
        _uiState.update { state ->
            val question = state.question ?: return@update state
            val updated = if (question.type == "multi_choice") {
                val maxSel = (question.answerConfig as? ChoiceAnswerConfigImpl)?.config?.maxSelections ?: 0
                when {
                    optionId in state.pendingSelectedOptionIds -> state.pendingSelectedOptionIds - optionId
                    maxSel == 0 || state.pendingSelectedOptionIds.size < maxSel -> state.pendingSelectedOptionIds + optionId
                    else -> state.pendingSelectedOptionIds
                }
            } else {
                listOf(optionId)
            }
            state.copy(pendingSelectedOptionIds = updated, submitted = false)
        }
    }

    fun updateScale(value: Int) {
        _uiState.update { it.copy(pendingScaleValue = value, submitted = false) }
    }

    fun submitAnswer() {
        val state = _uiState.value
        val question = state.question ?: return
        if (!canSubmit(state)) return
        viewModelScope.launch {
            localAnswerRepository.saveAnswer(state.toLocalAnswer(question))
            _uiState.update { it.copy(submitted = true) }
        }
    }

    fun canSubmit(): Boolean = canSubmit(_uiState.value)

    companion object {
        const val MAX_ANSWER_LENGTH = 2000
    }

    private fun canSubmit(state: LocalQuestionUiState): Boolean {
        val question = state.question ?: return false
        return when (question.type) {
            "written" -> state.pendingWrittenText.isNotBlank()
            "single_choice", "multi_choice", "this_or_that" -> state.pendingSelectedOptionIds.isNotEmpty()
            "scale" -> true
            else -> false
        }
    }
}
