// SPDX-License-Identifier: GPL-3.0-or-later
// MyIce Kotlin Multiplatform — schedule/convocation viewer
// Copyright (C) 2026 parano.ch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
package ch.parano.myicek.viewmodel
import ch.parano.myicek.auth.AuthSettings
import ch.parano.myicek.auth.OAuthClient
import ch.parano.myicek.network.ApiConfig
import ch.parano.myicek.network.ApiService
import ch.parano.myicek.network.AuthTokenHolder
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
sealed class AuthState {
data object Loading : AuthState()
data class Authenticated(val email: String) : AuthState()
data object Unauthenticated : AuthState()
}
class AuthViewModel(
private val apiService: ApiService,
private val authSettings: AuthSettings,
private val oauthClient: OAuthClient,
) : ViewModel() {
private val _state = MutableStateFlow(AuthState.Loading)
val state: StateFlow = _state.asStateFlow()
fun init() {
viewModelScope.launch {
val token = authSettings.getStoredToken()
if (token != null) {
AuthTokenHolder.token = token
try {
val userInfo = apiService.getUserInfo()
_state.value = AuthState.Authenticated(userInfo.email)
} catch (e: Exception) {
authSettings.clear()
_state.value = AuthState.Unauthenticated
}
} else {
_state.value = AuthState.Unauthenticated
}
}
}
fun login() {
viewModelScope.launch {
_state.value = AuthState.Loading
try {
val loginUrl = "${ApiConfig.baseUrl}/login?redirect_uri=" +
oauthClient.redirectUri()
val token = oauthClient.authenticate(loginUrl)
if (token != null) {
authSettings.setToken(token)
val userInfo = apiService.getUserInfo()
_state.value = AuthState.Authenticated(userInfo.email)
} else {
_state.value = AuthState.Unauthenticated
}
} catch (e: Exception) {
_state.value = AuthState.Unauthenticated
}
}
}
fun logout() {
authSettings.clear()
_state.value = AuthState.Unauthenticated
}
}