package com.seven.ikar.kotlin.feature.transfer

import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.seven.ikar.kotlin.app.IkarNativeApp
import com.seven.ikar.kotlin.core.local.TransferQueueStatus
import com.seven.ikar.kotlin.core.local.TransferQueueTypes

class TextMessageWorker(
    appContext: Context,
    params: WorkerParameters
) : CoroutineWorker(appContext, params) {
    override suspend fun doWork(): Result {
        val groupId = inputData.getString(KeyGroupId) ?: return Result.failure()
        val container = (applicationContext as IkarNativeApp).container
        val dao = container.localDatabase.transferQueueDao()
        val item = dao.getGroup(groupId).firstOrNull() ?: return Result.success()
        if (item.type != TransferQueueTypes.TextMessage) {
            return Result.failure()
        }

        val chatId = item.chatId ?: return Result.failure()
        val text = item.text?.takeIf(String::isNotBlank) ?: return Result.failure()
        val clientMessageId = item.clientMessageId ?: groupId
        dao.updateGroupStatus(groupId, TransferQueueStatus.Running, 25, null, System.currentTimeMillis())

        return runCatching {
            container.executeAuthorized { session ->
                val message = container.apiClient.sendMessage(
                    chatId = chatId,
                    text = text,
                    accessToken = session.accessToken,
                    replyToMessageId = item.replyToMessageId,
                    clientMessageId = clientMessageId
                )
                container.chatMessageCache.upsertMessages(session.user.id, chatId, listOf(message))
            }
        }.fold(
            onSuccess = {
                dao.updateGroupStatus(groupId, TransferQueueStatus.Completed, 100, null, System.currentTimeMillis())
                container.realtimeService.notifyChatsChangedLocally()
                Result.success()
            },
            onFailure = { error ->
                dao.updateGroupStatus(
                    groupId,
                    TransferQueueStatus.Failed,
                    0,
                    error.message,
                    System.currentTimeMillis()
                )
                if (runAttemptCount < MaxAutomaticRetries) Result.retry() else Result.failure()
            }
        )
    }

    companion object {
        const val KeyGroupId = "group_id"
        private const val MaxAutomaticRetries = 5
    }
}
