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 SignUpUiState(
    val email: String = "",
    val password: String = "",
    val confirmPassword: String = "",
    val isPasswordVisible: Boolean = false,
    val isLoading: Boolean = false,
    val error: String? = null,
    val success: Boolean = false,
    // Google sign-up: profile already comes from Google, so route through ONBOARDING
    // (which decides HOME vs CREATE_PROFILE) rather than the email CREATE_PROFILE step.
    val googleSuccess: Boolean = false
)

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

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

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

    fun signUp() {
        val state = _uiState.value
        val pw = state.password
        when {
            state.email.isBlank() -> { _uiState.update { it.copy(error = "Please enter your email.") }; return }
            pw.length < 8 -> { _uiState.update { it.copy(error = "Password must be at least 8 characters.") }; return }
            !pw.any { it.isLetter() } || !pw.any { it.isDigit() } -> { _uiState.update { it.copy(error = "Password must include both letters and numbers.") }; return }
            pw != state.confirmPassword -> { _uiState.update { it.copy(error = "Passwords don't match.") }; return }
        }
        _uiState.update { it.copy(isLoading = true, error = null) }
        viewModelScope.launch {
            authRepository.signUpWithEmail(state.email.trim(), pw)
                .onSuccess {
                    // Best-effort: send a verification email. Don't block account creation if it fails.
                    authRepository.sendEmailVerification()
                    _uiState.update { it.copy(isLoading = false, success = true) }
                }
                .onFailure { e ->
                    val msg = friendlyError(e)
                    _uiState.update { it.copy(isLoading = false, error = msg) }
                }
        }
    }

    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, googleSuccess = true) }
                }
                .onFailure { e -> _uiState.update { it.copy(isLoading = false, error = friendlyError(e)) } }
        }
    }

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

    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("email address is already") == true -> "An account with this email already exists."
        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."
    }
}
