package ru.myitschool.work.ui.screen.auth

import android.os.CountDownTimer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import ru.myitschool.work.core.Constants
import ru.myitschool.work.data.repo.AuthRepository
import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase
import ru.myitschool.work.domain.auth.CheckCodeFormatUseCase
import ru.myitschool.work.ui.nav.MainScreenDestination

class AuthViewModel : ViewModel() {
    private val checkCodeFormatUseCase by lazy { CheckCodeFormatUseCase() }
    private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) }
    private val _uiState = MutableStateFlow<AuthState>(
        AuthState.Data(
            isEnabledSend = false,
            error = null
        )
    )
    val uiState: StateFlow<AuthState> = _uiState.asStateFlow()

    private val _actionFlow: MutableSharedFlow<AuthAction> = MutableSharedFlow()
    val actionFlow: SharedFlow<AuthAction> = _actionFlow

    private var authTries: Int = 0
    private var timerSecs: Int = 0

    private var login: String = ""
    private var password: String = ""

    fun onIntent(intent: AuthIntent) {
        when (intent) {
            is AuthIntent.Send -> {
                if (authTries >= 5) {
                    timerSecs = Constants.AUTH_DELAY
                    val timer = object : CountDownTimer((timerSecs * 1000).toLong(), 1000) {
                        override fun onTick(millisUntilFinished: Long) {
                            timerSecs -= 1
                            updateStateIfData { oldState ->
                                oldState.copy(
                                    isEnabledSend = false,
                                    error = "Слишком много попыток входа, попробуйте через $timerSecs секунд"
                                )
                            }
                        }

                        override fun onFinish() {
                            authTries = 0
                            updateStateIfData { oldState ->
                                oldState.copy(
                                    isEnabledSend = checkCodeFormatUseCase.invoke(
                                        login = login,
                                        password = password
                                    ),
                                    error = null
                                )
                            }
                        }
                    }
                    timer.start()
                } else {
                    viewModelScope.launch {
                        _uiState.update { AuthState.Loading }
                        checkAndSaveAuthCodeUseCase.invoke(intent.login, intent.password).fold(
                            onSuccess = {
                                _actionFlow.emit(AuthAction.Open(MainScreenDestination))
                            },
                            onFailure = { error ->
                                authTries += 1
                                _uiState.update { AuthState.Data(isEnabledSend = false, error = error.message) }
                            }
                        )
                    }
                }
            }

            is AuthIntent.TextInput -> {
                login = intent.login
                password = intent.password
                updateStateIfData { oldState ->
                    oldState.copy(
                        isEnabledSend = checkCodeFormatUseCase.invoke(
                            login = intent.login,
                            password = intent.password
                        ) && authTries <= 5,
                        error = if (authTries >= 5) oldState.error else null
                    )
                }
            }
        }
    }

    private fun updateStateIfData(lambda: (AuthState.Data) -> AuthState) {
        _uiState.update { state ->
            (state as? AuthState.Data)?.let { lambda.invoke(it) } ?: state
        }

    }
}