package app.closer.ui.questions

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.data.local.QuestionDao
import app.closer.data.local.mapper.toQuestion
import app.closer.domain.model.ChoiceAnswerConfigImpl
import app.closer.domain.model.Question
import app.closer.domain.model.QuestionAnswer
import app.closer.domain.model.QuestionMessage
import app.closer.domain.model.QuestionReaction
import app.closer.domain.repository.QuestionThreadRepository
import com.google.firebase.auth.FirebaseAuth
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

enum class QuestionPhase { INPUT, WAITING, REVEALED }

data class QuestionThreadUiState(
    val isLoading: Boolean = true,
    val error: String? = null,
    val question: Question? = null,
    val threadId: String? = null,
    val phase: QuestionPhase = QuestionPhase.INPUT,
    val myAnswer: QuestionAnswer? = null,
    val partnerAnswer: QuestionAnswer? = null,
    val messages: List<QuestionMessage> = emptyList(),
    val reactions: List<QuestionReaction> = emptyList(),
    val pendingWrittenText: String = "",
    val pendingSelectedOptionIds: List<String> = emptyList(),
    val pendingScaleValue: Int = 3,
    val messageInput: String = "",
    val helpExpanded: Boolean = false,
    val isSubmitting: Boolean = false,
    val previousQuestionId: String? = null,
    val nextQuestionId: String? = null
)

@HiltViewModel
class QuestionThreadViewModel @Inject constructor(
    private val repository: QuestionThreadRepository,
    private val questionDao: QuestionDao,
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val coupleId: String = savedStateHandle["coupleId"] ?: ""
    private val questionId: String = savedStateHandle["questionId"] ?: ""
    val currentUserId: String = FirebaseAuth.getInstance().currentUser?.uid ?: ""

    private val _uiState = MutableStateFlow(
        QuestionThreadUiState(
            previousQuestionId = savedStateHandle["prevId"],
            nextQuestionId = savedStateHandle["nextId"]
        )
    )
    val uiState: StateFlow<QuestionThreadUiState> = _uiState.asStateFlow()

    init {
        loadThread()
    }

    private fun loadThread() {
        viewModelScope.launch {
            try {
                val entity = questionDao.getQuestionById(questionId)
                val question = entity?.toQuestion()
                if (question == null) {
                    _uiState.update { it.copy(isLoading = false, error = "Question not found") }
                    return@launch
                }
                _uiState.update { it.copy(question = question, isLoading = false) }

                val threadId = repository.findOrCreateThreadId(coupleId, questionId, question.category, currentUserId)
                _uiState.update { it.copy(threadId = threadId) }

                launch {
                    repository.observeAnswers(coupleId, threadId).collect { answers ->
                        val my = answers.find { it.userId == currentUserId }
                        val partner = answers.find { it.userId != currentUserId }
                        val phase = when {
                            my == null -> QuestionPhase.INPUT
                            partner == null -> QuestionPhase.WAITING
                            else -> QuestionPhase.REVEALED
                        }
                        _uiState.update { state ->
                            state.copy(
                                phase = phase,
                                myAnswer = my,
                                partnerAnswer = if (phase == QuestionPhase.REVEALED) partner else null
                            )
                        }
                    }
                }
                launch {
                    repository.observeMessages(coupleId, threadId).collect { msgs ->
                        _uiState.update { it.copy(messages = msgs) }
                    }
                }
                launch {
                    repository.observeReactions(coupleId, threadId).collect { reactions ->
                        _uiState.update { it.copy(reactions = reactions) }
                    }
                }
            } catch (e: Exception) {
                _uiState.update { it.copy(isLoading = false, error = e.message) }
            }
        }
    }

    // ─── Answer input mutations ──────────────────────────────────────────────────

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

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

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

    fun submitAnswer() {
        val state = _uiState.value
        val threadId = state.threadId ?: return
        val question = state.question ?: return
        if (state.isSubmitting) return
        if (currentUserId.isEmpty()) return

        _uiState.update { it.copy(isSubmitting = true) }
        viewModelScope.launch {
            try {
                val answer = buildAnswer(state, question)
                repository.submitAnswer(coupleId, threadId, currentUserId, answer)
            } catch (e: Exception) {
                _uiState.update { it.copy(error = e.message) }
            } finally {
                _uiState.update { it.copy(isSubmitting = false) }
            }
        }
    }

    private fun buildAnswer(state: QuestionThreadUiState, question: Question): QuestionAnswer {
        val now = System.currentTimeMillis()
        return QuestionAnswer(
            userId = currentUserId,
            questionId = questionId,
            answerType = question.type,
            writtenText = if (question.type == "written") state.pendingWrittenText else null,
            selectedOptionIds = when (question.type) {
                "single_choice", "multi_choice", "this_or_that" -> state.pendingSelectedOptionIds
                else -> emptyList()
            },
            scaleValue = if (question.type == "scale") state.pendingScaleValue else null,
            createdAt = now,
            updatedAt = now
        )
    }

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

    // ─── Help expandable ─────────────────────────────────────────────────────────

    fun toggleHelp() {
        _uiState.update { it.copy(helpExpanded = !it.helpExpanded) }
    }

    // ─── Discussion ──────────────────────────────────────────────────────────────

    fun updateMessageInput(text: String) {
        _uiState.update { it.copy(messageInput = text.take(MAX_MESSAGE_LENGTH)) }
    }

    fun sendMessage() {
        val state = _uiState.value
        val threadId = state.threadId ?: return
        if (state.phase != QuestionPhase.REVEALED) return
        if (currentUserId.isEmpty()) return
        val text = state.messageInput.trim()
        if (text.isBlank()) return

        _uiState.update { it.copy(messageInput = "") }
        viewModelScope.launch {
            try {
                val msg = QuestionMessage(
                    userId = currentUserId,
                    text = text,
                    createdAt = System.currentTimeMillis()
                )
                repository.sendMessage(coupleId, threadId, msg)
            } catch (e: Exception) {
                _uiState.update { it.copy(error = e.message) }
            }
        }
    }

    // ─── Reactions ───────────────────────────────────────────────────────────────

    fun addReaction(targetUserId: String, emoji: String) {
        val state = _uiState.value
        val threadId = state.threadId ?: return
        if (state.phase != QuestionPhase.REVEALED) return
        if (currentUserId.isEmpty()) return

        viewModelScope.launch {
            try {
                val reaction = QuestionReaction(
                    userId = currentUserId,
                    targetUserId = targetUserId,
                    emoji = emoji,
                    createdAt = System.currentTimeMillis()
                )
                repository.addReaction(coupleId, threadId, reaction)
            } catch (e: Exception) {
                _uiState.update { it.copy(error = e.message) }
            }
        }
    }

    fun dismissError() {
        _uiState.update { it.copy(error = null) }
    }

    companion object {
        const val MAX_ANSWER_LENGTH = 2000
        const val MAX_MESSAGE_LENGTH = 500
    }
}
