package dev.zxq5.chatapp.android.data.repository

import dev.zxq5.chatapp.android.api.AuthClient
import dev.zxq5.chatapp.android.core.data.TokenStore
import dev.zxq5.chatapp.android.core.data.getScopeFromToken
import dev.zxq5.chatapp.android.core.error.ApiResult
import dev.zxq5.chatapp.android.feature.auth.TokenScope

class AuthRepository(
    private val tokenStore: TokenStore,
) {
    suspend fun signup(username: String, email: String, password: String, accessToken: String): SignupResult {
        return when(val result = AuthClient.signup(username, email, password, accessToken)) {
            is ApiResult.HttpError -> SignupResult.Error(result.message)
            is ApiResult.NetworkError -> SignupResult.Error("Network error: ${result.message}")
            is ApiResult.Success -> {
                tokenStore.save(result.data.token)
                SignupResult.Success
            }
        }
    }

    suspend fun verifyTotpLogin(code: String): LoginResult {
        val partialToken = tokenStore.get() ?: return LoginResult.Error("Session expired")
        return when(val result = AuthClient.verifyTotpLogin(partialToken, code)) {
            is ApiResult.HttpError -> LoginResult.TotpError(result.message)
            is ApiResult.NetworkError -> LoginResult.TotpError("Network error: ${result.message}")
            is ApiResult.Success -> {
                tokenStore.save(result.data.token)
                LoginResult.Success
            }
        }
    }

    suspend fun login(username: String, password: String): LoginResult {
        return when(val result = AuthClient.login(username, password)) {
            is ApiResult.HttpError -> LoginResult.Error(result.message)
            is ApiResult.NetworkError -> LoginResult.Error("Network error: ${result.message}")
            is ApiResult.Success -> {
                tokenStore.save(result.data.token)

                when (val scope = getScopeFromToken(result.data.token)) {
                    TokenScope.TOTP_PENDING -> LoginResult.TotpRequired
                    TokenScope.FULL -> LoginResult.Success
                    else -> LoginResult.Error("Unexpected token scope: $scope")
                }
            }
       }
    }

    fun logout() {
        tokenStore.clear()
    }
    
    fun getUserId() = tokenStore.getUserId()

    fun getAuthState(): AuthState {
        val token = tokenStore.get() ?: return AuthState.Unauthenticated
        if (tokenStore.isExpired()) {
            tokenStore.clear()
            return AuthState.Unauthenticated
        }
        return when (getScopeFromToken(token)) {
            TokenScope.FULL -> AuthState.Authenticated
            TokenScope.TOTP_PENDING -> AuthState.AwaitingTotp
            else -> AuthState.Unauthenticated
        }
    }
}

sealed class SignupResult {
    object Success : SignupResult()
    data class Error(val message: String) : SignupResult()
}

sealed class LoginResult {
    object Success : LoginResult()
    object TotpRequired : LoginResult()
    data class TotpError(val message: String) : LoginResult()
    data class Error(val message: String) : LoginResult()
}

sealed class AuthState {
    object Authenticated : AuthState()
    object AwaitingTotp : AuthState()
    object Unauthenticated : AuthState()
}
