package app.closer.ui.pairing

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.core.navigation.AppRoute
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.CoupleRepository
import app.closer.domain.repository.InviteRepository
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.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

data class CreateInviteUiState(
    val isLoading: Boolean = true,
    val inviteCode: String? = null,
    val recoveryPhrase: String? = null,
    val error: String? = null,
    val navigateTo: String? = null
)

@HiltViewModel
class CreateInviteViewModel @Inject constructor(
    private val authRepository: AuthRepository,
    private val inviteRepository: InviteRepository,
    private val coupleRepository: CoupleRepository
) : ViewModel() {

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

    init {
        viewModelScope.launch {
            val userId = authRepository.currentUserId ?: run {
                _uiState.update { it.copy(isLoading = false, error = "Not signed in.") }
                return@launch
            }
            val couple = coupleRepository.getCoupleForUser(userId)
            if (couple != null) {
                _uiState.update { it.copy(isLoading = false, navigateTo = AppRoute.HOME) }
                return@launch
            }
            inviteRepository.createInvite()
                .onSuccess { result ->
                    _uiState.update { it.copy(isLoading = false, inviteCode = result.code, recoveryPhrase = result.recoveryPhrase) }
                    watchForAcceptance(result.code)
                }
                .onFailure { e ->
                    Log.e(TAG, "createInvite failed", e)
                    _uiState.update { it.copy(isLoading = false, error = e.message ?: "Couldn't create invite. Please try again.") }
                }
        }
    }

    private fun watchForAcceptance(code: String) {
        viewModelScope.launch {
            val coupleId = inviteRepository.watchAccepted(code).filterNotNull().first()
            _uiState.update { it.copy(navigateTo = AppRoute.pairingSuccess(coupleId)) }
        }
    }

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

    companion object {
        private const val TAG = "CreateInviteViewModel"
    }
}
