package com.zaojiao.app.core.auth.data

import android.content.Context
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStoreFile
import com.zaojiao.app.core.auth.model.TokenModel
import com.zaojiao.app.core.common.remote.AppDispatchers
import com.zaojiao.app.core.common.remote.Dispatcher
import com.zaojiao.app.core.common.remote.di.ApplicationScope
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class LocalAuthData @Inject constructor(
    @ApplicationContext context: Context,
    @Dispatcher(AppDispatchers.IO) ioDispatcher: CoroutineDispatcher,
    @ApplicationScope scope: CoroutineScope,
) {
    private val tokenPreferences = PreferenceDataStoreFactory.create(
        scope = CoroutineScope(scope.coroutineContext + ioDispatcher),
    ) {
        context.preferencesDataStoreFile("token")
    }

    private val accessTokenKey = stringPreferencesKey("access_token")
    private val refreshTokenKey = stringPreferencesKey("refreshToken")

    val token = tokenPreferences.data.map {
        it.run {
            val accessToken = this[accessTokenKey]
            val refreshToken = this[refreshTokenKey]

            return@map if (accessToken == null) {
                null
            } else {
                if (refreshToken == null) {
                    clearToken()
                    null
                } else {
                    TokenModel(
                        accessToken = accessToken,
                        refreshToken = refreshToken,
                    )
                }
            }
        }
    }

    suspend fun updateToken(token: TokenModel) {
        tokenPreferences.edit {
            it[accessTokenKey] = token.accessToken
            it[refreshTokenKey] = token.refreshToken
        }
    }

    suspend fun clearToken() {
        tokenPreferences.edit { token -> token.clear() }
    }
}