package com.seven.ikar.kotlin.feature.login

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.seven.ikar.kotlin.app.AppContainer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

data class LoginUiState(
    val phoneNumber: String = "",
    val displayName: String = "",
    val verificationCode: String = "",
    val challengeId: String = "",
    val testCodeHint: String = "",
    val isAwaitingCode: Boolean = false,
    val isNewAccount: Boolean = false,
    val isLoading: Boolean = false,
    val errorMessage: String? = null,
    val isAuthenticated: Boolean = false
) {
    val pageTitle: String
        get() = if (isAwaitingCode) "Подтвердите номер" else "Вход в ИКАР"

    val subtitle: String
        get() = if (isAwaitingCode) {
            "Введите тестовый код. Когда подключим SMS-провайдера, здесь будет код из сообщения."
        } else {
            "Введите номер телефона, чтобы получить тестовый код входа."
        }

    val showPhoneStep: Boolean
        get() = !isAwaitingCode

    val showCodeStep: Boolean
        get() = isAwaitingCode

    val showDisplayName: Boolean
        get() = isAwaitingCode && isNewAccount

    val hasTestCodeHint: Boolean
        get() = testCodeHint.isNotBlank()
}

class LoginViewModel(private val container: AppContainer) : ViewModel() {
    private val _uiState = MutableStateFlow(LoginUiState())
    val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()

    fun updatePhoneNumber(value: String) {
        _uiState.value = _uiState.value.copy(phoneNumber = value, errorMessage = null)
    }

    fun updateDisplayName(value: String) {
        _uiState.value = _uiState.value.copy(displayName = value, errorMessage = null)
    }

    fun updateVerificationCode(value: String) {
        _uiState.value = _uiState.value.copy(verificationCode = value, errorMessage = null)
    }

    fun requestCode() {
        val state = _uiState.value
        if (state.phoneNumber.isBlank() || state.isLoading) {
            return
        }

        viewModelScope.launch(Dispatchers.IO) {
            _uiState.value = state.copy(isLoading = true, errorMessage = null)
            runCatching {
                container.apiClient.requestPhoneCode(state.phoneNumber.trim())
            }.onSuccess { challenge ->
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    challengeId = challenge.challengeId,
                    testCodeHint = challenge.testCode,
                    isAwaitingCode = true,
                    isNewAccount = !challenge.isRegistered,
                    verificationCode = "",
                    errorMessage = null
                )
            }.onFailure { error ->
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    errorMessage = error.message ?: "Не удалось запросить код."
                )
            }
        }
    }

    fun verifyCode() {
        val state = _uiState.value
        if (state.isLoading ||
            state.challengeId.isBlank() ||
            state.phoneNumber.isBlank() ||
            state.verificationCode.isBlank() ||
            (state.isNewAccount && state.displayName.isBlank())
        ) {
            return
        }

        viewModelScope.launch(Dispatchers.IO) {
            _uiState.value = state.copy(isLoading = true, errorMessage = null)
            runCatching {
                container.apiClient.verifyPhoneCode(
                    challengeId = state.challengeId,
                    phoneNumber = state.phoneNumber.trim(),
                    code = state.verificationCode.trim(),
                    displayName = state.displayName.trim().ifBlank { null }
                )
            }.onSuccess { session ->
                container.sessionStore.save(session)
                runCatching { container.pushRegistrationManager.registerCurrentDeviceAsync() }
                _uiState.value = _uiState.value.copy(isLoading = false, isAuthenticated = true)
            }.onFailure { error ->
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    errorMessage = error.message ?: "Не удалось подтвердить код."
                )
            }
        }
    }

    fun changePhoneNumber() {
        _uiState.value = _uiState.value.copy(
            challengeId = "",
            testCodeHint = "",
            verificationCode = "",
            isAwaitingCode = false,
            isNewAccount = false,
            errorMessage = null
        )
    }
}
