package de.tsschulz.tt_tagebuch.shared.state

import de.tsschulz.tt_tagebuch.shared.api.AuthApi
import de.tsschulz.tt_tagebuch.shared.api.SessionApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

class AuthManager(
    private val tokenProvider: MutableTokenProvider,
    private val tokenStorage: TokenStorage,
    private val authApi: AuthApi,
    private val sessionApi: SessionApi,
) : TokenProvider {

    private val _state = MutableStateFlow(AuthState(isHydrating = true))
    val state: StateFlow<AuthState> = _state.asStateFlow()

    override val token: String? get() = tokenProvider.token
    override val username: String? get() = tokenProvider.username

    suspend fun hydrate() {
        _state.value = _state.value.copy(isHydrating = true)
        try {
            val stored = tokenStorage.load()
            if (stored != null) {
                tokenProvider.token = stored.token
                tokenProvider.username = stored.username
                _state.value = AuthState(token = stored.token, username = stored.username, isHydrating = true)

                val status = runCatching { sessionApi.status() }.getOrNull()
                if (status != null && !status.valid) {
                    clearLocal()
                }
            } else {
                clearLocal()
            }
        } finally {
            _state.value = _state.value.copy(isHydrating = false)
        }
    }

    suspend fun login(email: String, password: String) {
        val response = authApi.login(email = email, password = password)
        val tokens = AuthTokens(token = response.token, username = email)
        tokenProvider.token = tokens.token
        tokenProvider.username = tokens.username
        tokenStorage.save(tokens)
        _state.value = AuthState(token = tokens.token, username = tokens.username, isHydrating = false)
    }

    suspend fun logout() {
        runCatching { authApi.logout() }
        clearLocal()
    }

    suspend fun deleteAccount(password: String) {
        authApi.deleteAccount(password)
        clearLocal()
    }

    suspend fun clearLocal() {
        tokenProvider.token = null
        tokenProvider.username = null
        tokenStorage.clear()
        _state.value = AuthState(token = null, username = null, isHydrating = false)
    }
}
