package app.closer.ui.auth

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.closer.domain.model.GoogleSignInResult
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

data class LoginUiState(
    val email: String = "",
    val password: String = "",
    val isPasswordVisible: Boolean = false,
    val isLoading: Boolean = false,
    val error: String? = null,
    val success: Boolean = false
)

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

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

    fun updateEmail(email: String) = _uiState.update { it.copy(email = email, error = null) }
    fun updatePassword(pw: String) = _uiState.update { it.copy(password = pw, error = null) }
    fun togglePasswordVisibility() = _uiState.update { it.copy(isPasswordVisible = !it.isPasswordVisible) }
    fun dismissError() = _uiState.update { it.copy(error = null) }

    fun signIn() {
        val state = _uiState.value
        if (state.email.isBlank() || state.password.isBlank()) {
            _uiState.update { it.copy(error = "Please enter your email and password.") }
            return
        }
        attemptSignIn { authRepository.signInWithEmail(state.email.trim(), state.password) }
    }

    fun signInWithGoogle(idToken: String) {
        _uiState.update { it.copy(isLoading = true, error = null) }
        viewModelScope.launch {
            authRepository.signInWithGoogle(idToken)
                .onSuccess { result ->
                    mergeGoogleProfile(result)
                    _uiState.update { it.copy(isLoading = false, success = true) }
                }
                .onFailure { e -> _uiState.update { it.copy(isLoading = false, error = friendlyError(e)) } }
        }
    }

    fun reportError(message: String) = _uiState.update { it.copy(error = message) }

    private fun attemptSignIn(action: suspend () -> Result<String>) {
        _uiState.update { it.copy(isLoading = true, error = null) }
        viewModelScope.launch {
            action()
                .onSuccess { _uiState.update { it.copy(isLoading = false, success = true) } }
                .onFailure { e -> _uiState.update { it.copy(isLoading = false, error = friendlyError(e)) } }
        }
    }

    private suspend fun mergeGoogleProfile(result: GoogleSignInResult) {
        val uid = result.uid
        if (uid.isBlank()) return
        val existing = runCatching { userRepository.getUser(uid) }.getOrNull()
        if (existing == null) {
            userRepository.createUser(
                User(
                    id = uid,
                    email = result.email,
                    displayName = result.displayName,
                    photoUrl = result.photoUrl,
                    createdAt = System.currentTimeMillis(),
                    lastActiveAt = System.currentTimeMillis()
                )
            )
        } else {
            if (existing.displayName.isBlank() && result.displayName.isNotBlank()) {
                userRepository.updateDisplayName(uid, result.displayName)
            }
            if (existing.photoUrl.isBlank() && result.photoUrl.isNotBlank()) {
                userRepository.updatePhotoUrl(uid, result.photoUrl)
            }
        }
    }

    private fun friendlyError(e: Throwable): String = when {
        e.message?.contains("no user record") == true -> "No account found with that email."
        e.message?.contains("password is invalid") == true -> "Incorrect password."
        e.message?.contains("badly formatted") == true -> "Please enter a valid email address."
        e.message?.contains("network") == true -> "Check your connection and try again."
        else -> e.message ?: "Something went wrong. Please try again."
    }
}
