package cy.hexor.furumi.ui.login

import android.net.Uri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cy.hexor.furumi.domain.model.ServerConfig
import cy.hexor.furumi.domain.repository.AuthRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

data class LoginUiState(
    val serverUrl: String = "",
    val login: String = "",
    val password: String = "",
    val isLoading: Boolean = false,
    val loadingAction: LoginLoadingAction? = null,
    val error: String? = null,
    val isAuthenticated: Boolean = false,
    val externalAuthUrl: String? = null
)

enum class LoginLoadingAction {
    Password,
    Sso
}

@HiltViewModel
class LoginViewModel @Inject constructor(
    private val authRepository: AuthRepository
) : ViewModel() {
    private val _uiState = MutableStateFlow(
        LoginUiState(
            serverUrl = authRepository.getSavedServerUrl()?.takeIf { it.isNotBlank() } ?: DEFAULT_SERVER_URL,
            isAuthenticated = authRepository.getCurrentSession() != null
        )
    )
    val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()

    fun onServerUrlChange(url: String) {
        _uiState.value = _uiState.value.copy(serverUrl = url.withoutLineBreaks(), error = null)
    }

    fun onLoginChange(login: String) {
        _uiState.value = _uiState.value.copy(login = login.withoutLineBreaks(), error = null)
    }

    fun onPasswordChange(password: String) {
        _uiState.value = _uiState.value.copy(password = password.withoutLineBreaks(), error = null)
    }

    fun login() {
        val state = _uiState.value
        val password = state.password

        if (password.isBlank()) {
            _uiState.value = _uiState.value.copy(error = "Password is required")
            return
        }

        val config = ServerConfig.credentials(state.serverUrl, state.login).getOrElse {
            _uiState.value = _uiState.value.copy(error = it.message ?: "Check your login details")
            return
        }

        viewModelScope.launch {
            _uiState.value = _uiState.value.copy(
                isLoading = true,
                loadingAction = LoginLoadingAction.Password,
                error = null
            )
            
            val result = authRepository.login(
                config = config,
                password = password
            )
            
            result.onSuccess {
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    loadingAction = null,
                    password = "",
                    serverUrl = it.serverBaseUrl,
                    isAuthenticated = true
                )
            }.onFailure {
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    loadingAction = null,
                    error = it.message
                )
            }
        }
    }

    fun loginWithSSO() {
        val state = _uiState.value

        viewModelScope.launch {
            _uiState.value = _uiState.value.copy(
                isLoading = true,
                loadingAction = LoginLoadingAction.Sso,
                error = null
            )

            authRepository.createSsoAuthorizationUrl(state.serverUrl)
                .onSuccess { authUrl ->
                    _uiState.value = _uiState.value.copy(
                        isLoading = false,
                        loadingAction = null,
                        externalAuthUrl = authUrl
                    )
                }
                .onFailure {
                    _uiState.value = _uiState.value.copy(
                        isLoading = false,
                        loadingAction = null,
                        error = it.message ?: "Unable to start SSO login"
                    )
                }
        }
    }

    fun onExternalAuthUrlOpened() {
        _uiState.value = _uiState.value.copy(externalAuthUrl = null)
    }

    fun handleDeepLink(uri: Uri?) {
        val callbackUrl = uri?.toString() ?: return

        viewModelScope.launch {
            _uiState.value = _uiState.value.copy(
                isLoading = true,
                loadingAction = LoginLoadingAction.Sso,
                error = null
            )
            val result = authRepository.completeSsoLogin(callbackUrl)
            result.onSuccess {
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    loadingAction = null,
                    serverUrl = it.serverBaseUrl,
                    isAuthenticated = true
                )
            }.onFailure {
                _uiState.value = _uiState.value.copy(
                    isLoading = false,
                    loadingAction = null,
                    error = it.message
                )
            }
        }
    }

    private fun String.withoutLineBreaks(): String {
        return replace("\r", "").replace("\n", "")
    }

    private companion object {
        const val DEFAULT_SERVER_URL = "https://music.hexor.cy"
    }
}
