package app.closer.ui.onboarding

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

enum class ProfileStep {
    NAME,
    SEX,
    PHOTO
}

data class CreateProfileUiState(
    val currentStep: ProfileStep = ProfileStep.NAME,
    val displayName: String = "",
    val sex: String = "",
    val photoUrl: String = "",
    val photoUri: String? = null,
    val isLoading: Boolean = false,
    val error: String? = null,
    val success: Boolean = false,
    val nameError: String? = null,
    val sexError: String? = null
)

@HiltViewModel
class CreateProfileViewModel @Inject constructor(
    private val authRepository: AuthRepository,
    private val userRepository: UserRepository,
    private val storageDataSource: FirebaseStorageDataSource
) : ViewModel() {

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

    init {
        loadExistingProfile()
    }

    private fun loadExistingProfile() {
        val uid = authRepository.currentUserId ?: return
        viewModelScope.launch {
            val user = runCatching { userRepository.getUser(uid) }.getOrNull() ?: return@launch
            _uiState.update {
                it.copy(
                    displayName = user.displayName,
                    sex = user.sex,
                    photoUrl = user.photoUrl
                )
            }
        }
    }

    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 goBack() {
        val previous = when (_uiState.value.currentStep) {
            ProfileStep.NAME -> ProfileStep.NAME
            ProfileStep.SEX -> ProfileStep.NAME
            ProfileStep.PHOTO -> ProfileStep.SEX
        }
        _uiState.update { it.copy(currentStep = previous, error = null) }
    }

    fun goToNextStep() {
        val state = _uiState.value
        when (state.currentStep) {
            ProfileStep.NAME -> {
                val name = state.displayName.trim()
                when {
                    name.isBlank() -> _uiState.update { it.copy(nameError = "Please enter your name.") }
                    name.length < 2 -> _uiState.update { it.copy(nameError = "Name must be at least 2 characters.") }
                    else -> _uiState.update { it.copy(currentStep = ProfileStep.SEX, nameError = null) }
                }
            }
            ProfileStep.SEX -> {
                if (state.sex.isBlank()) {
                    _uiState.update { it.copy(sexError = "Please select an option so we can tailor your experience.") }
                } else {
                    _uiState.update { it.copy(currentStep = ProfileStep.PHOTO, sexError = null) }
                }
            }
            ProfileStep.PHOTO -> saveProfile()
        }
    }

    fun skipPhoto() = saveProfile(skipPhoto = true)

    fun saveProfile(skipPhoto: Boolean = false) {
        val state = _uiState.value
        val name = state.displayName.trim()
        if (name.isBlank() || name.length < 2 || state.sex.isBlank()) {
            _uiState.update {
                it.copy(
                    nameError = if (name.isBlank()) "Please enter your name." else if (name.length < 2) "Name must be at least 2 characters." else null,
                    sexError = if (state.sex.isBlank()) "Please select your sex." else null
                )
            }
            return
        }
        val uid = authRepository.currentUserId ?: run {
            _uiState.update { it.copy(error = "Not signed in. Please sign in and try again.") }
            return
        }
        _uiState.update { it.copy(isLoading = true, error = null) }
        viewModelScope.launch {
            runCatching {
                val finalPhotoUrl = if (!skipPhoto && !state.photoUri.isNullOrBlank()) {
                    storageDataSource.uploadProfilePhoto(uid, Uri.parse(state.photoUri))
                } else {
                    state.photoUrl
                }
                val existing = userRepository.getUser(uid)
                val user = existing ?: User(
                    id = uid,
                    displayName = name,
                    sex = state.sex,
                    photoUrl = finalPhotoUrl,
                    createdAt = System.currentTimeMillis(),
                    lastActiveAt = System.currentTimeMillis()
                )
                if (existing == null) {
                    userRepository.createUser(user.copy(displayName = name, sex = state.sex, photoUrl = finalPhotoUrl))
                } else {
                    userRepository.updateDisplayName(uid, name)
                    userRepository.updateSex(uid, state.sex)
                    if (finalPhotoUrl.isNotBlank()) {
                        userRepository.updatePhotoUrl(uid, finalPhotoUrl)
                    }
                }
            }.onSuccess {
                _uiState.update { it.copy(isLoading = false, success = true) }
            }.onFailure { e ->
                _uiState.update { it.copy(isLoading = false, error = e.message ?: "Couldn't save your profile. Please try again.") }
            }
        }
    }

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