package app.closer.ui.settings

import android.net.Uri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.crypto.CoupleEncryptionManager
import app.closer.data.remote.FirebaseStorageDataSource
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.CoupleRepository
import app.closer.domain.repository.UserRepository
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

data class EditProfileUiState(
    val displayName: String = "",
    val sex: String = "",
    val photoUrl: String = "",
    val photoUri: String? = null,
    val email: String = "",
    val isAnonymous: Boolean = false,
    val isGoogleAccount: Boolean = false,
    val isLoading: Boolean = true,
    val isSaving: Boolean = false,
    val error: String? = null,
    val success: Boolean = false,
    val nameError: String? = null,
    val sexError: String? = null,
    val recoveryPhrase: String? = null
)

@HiltViewModel
class EditProfileViewModel @Inject constructor(
    private val authRepository: AuthRepository,
    private val userRepository: UserRepository,
    private val storageDataSource: FirebaseStorageDataSource,
    private val coupleRepository: CoupleRepository,
    private val encryptionManager: CoupleEncryptionManager
) : ViewModel() {

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

    init {
        loadProfile()
    }

    private fun loadProfile() {
        val uid = authRepository.currentUserId ?: run {
            _uiState.update { it.copy(isLoading = false, error = "Not signed in.") }
            return
        }
        viewModelScope.launch {
            val user = runCatching { userRepository.getUser(uid) }.getOrNull()
            val coupleId = runCatching { coupleRepository.getCoupleForUser(uid) }.getOrNull()?.id
            val phrase = coupleId?.let { encryptionManager.recoveryPhrase(it) }
            _uiState.update {
                it.copy(
                    isLoading = false,
                    displayName = user?.displayName ?: "",
                    sex = user?.sex ?: "",
                    photoUrl = user?.photoUrl ?: "",
                    email = authRepository.currentUserEmail ?: user?.email ?: "",
                    isAnonymous = authRepository.isAnonymous,
                    isGoogleAccount = authRepository.isGoogleAccount,
                    recoveryPhrase = phrase
                )
            }
        }
    }

    fun updateDisplayName(name: String) = _uiState.update { it.copy(displayName = name, nameError = null, error = null) }

    fun selectSex(sex: String) = _uiState.update { it.copy(sex = sex, sexError = null, error = null) }

    fun setPhotoUri(uri: String?) = _uiState.update { it.copy(photoUri = uri, error = null) }

    fun save() {
        val state = _uiState.value
        val name = state.displayName.trim()
        when {
            name.isBlank() -> {
                _uiState.update { it.copy(nameError = "Please enter your name.") }
                return
            }
            name.length < 2 -> {
                _uiState.update { it.copy(nameError = "Name must be at least 2 characters.") }
                return
            }
            state.sex.isBlank() -> {
                _uiState.update { it.copy(sexError = "Please select your sex.") }
                return
            }
        }
        val uid = authRepository.currentUserId ?: run {
            _uiState.update { it.copy(error = "Not signed in.") }
            return
        }
        _uiState.update { it.copy(isSaving = true, error = null) }
        viewModelScope.launch {
            runCatching {
                val finalPhotoUrl = if (!state.photoUri.isNullOrBlank()) {
                    storageDataSource.uploadProfilePhoto(uid, Uri.parse(state.photoUri))
                } else {
                    state.photoUrl
                }
                userRepository.updateDisplayName(uid, name)
                userRepository.updateSex(uid, state.sex)
                if (finalPhotoUrl.isNotBlank()) {
                    userRepository.updatePhotoUrl(uid, finalPhotoUrl)
                }
            }.onSuccess {
                _uiState.update { it.copy(isSaving = false, success = true, photoUri = null, photoUrl = it.photoUrl) }
                loadProfile()
            }.onFailure { e ->
                _uiState.update { it.copy(isSaving = false, error = e.message ?: "Couldn't save changes. Please try again.") }
            }
        }
    }

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