package com.seven.ikar.kotlin.core.push

import android.content.Context
import android.os.Build
import com.seven.ikar.kotlin.core.model.PushPlatform
import com.seven.ikar.kotlin.core.model.RegisterPushDeviceRequest
import com.seven.ikar.kotlin.core.network.ApiClient
import com.seven.ikar.kotlin.core.session.AuthorizedSessionManager
import com.seven.ikar.kotlin.core.session.SessionStore
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class PushRegistrationManager(
    private val context: Context,
    private val apiClient: ApiClient,
    private val sessionStore: SessionStore,
    private val authorizedSessionManager: AuthorizedSessionManager,
    private val settings: AndroidPushSettings
) {
    suspend fun initializeAsync() = withContext(Dispatchers.IO) {
        AndroidPushBootstrapper.tryInitialize(context)
    }

    suspend fun registerCurrentDeviceAsync() = withContext(Dispatchers.IO) {
        if (!AndroidPushBootstrapper.tryInitialize(context)) {
            return@withContext
        }

        val token = settings.getDeviceToken().takeUnless { it.isNullOrBlank() }
            ?: FirebaseTokenProvider.tryGetToken(context)
            ?: return@withContext

        settings.setDeviceToken(token)

        val request = RegisterPushDeviceRequest(
            platform = PushPlatform.Android,
            installationId = settings.getInstallationId(),
            deviceToken = token,
            deviceName = buildDeviceName(),
            notificationsEnabled = settings.areNotificationsEnabled() &&
                AndroidNotificationPermissionHelper.areNotificationsEnabled(context)
        )

        if (sessionStore.read() == null) {
            return@withContext
        }

        authorizedSessionManager.executeAuthorized { session ->
            apiClient.registerPushDevice(
                accessToken = session.accessToken,
                request = request
            )
        }
    }

    suspend fun unregisterCurrentDeviceAsync() = withContext(Dispatchers.IO) {
        if (sessionStore.read() == null) {
            return@withContext
        }

        authorizedSessionManager.executeAuthorized { session ->
            apiClient.unregisterPushDevice(
                accessToken = session.accessToken,
                installationId = settings.getInstallationId()
            )
        }
    }

    suspend fun onTokenRefreshedAsync(token: String) = withContext(Dispatchers.IO) {
        if (token.isBlank()) {
            return@withContext
        }

        settings.setDeviceToken(token)
        if (sessionStore.read() != null) {
            runCatching { registerCurrentDeviceAsync() }
        }
    }

    private fun buildDeviceName(): String =
        "${Build.MANUFACTURER ?: "Android"} ${Build.MODEL ?: "device"}".trim()
}
