package io.nexilis.service.core

import android.annotation.TargetApi
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.annotation.StringRes
import androidx.core.app.NotificationCompat
import androidx.work.CoroutineWorker
import androidx.work.ForegroundInfo
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import io.nexilis.service.R
import io.nexilis.service.Service
import io.nexilis.service.data.rooms.ApiRoomDatabase
import io.nexilis.service.tag
import java.io.File

class Outgoing(private val context: Context, parameters: WorkerParameters) :
    CoroutineWorker(context, parameters) {
    override suspend fun doWork(): Result {
        try {
            inputData.getString("data")?.let {
                ApiRoomDatabase.getDatabase(context).messageDao().getSync(it)?.let { message ->
                    val bodies = mutableMapOf(
                        "A18" to message.message_id,
                        "A00" to message.f_pin,
                        "A01" to message.l_pin,
                        "A19" to message.server_date.toString(),
                        "lcltm" to message.local_timestamp.toString(),
                        "A06" to message.message_scope_id,
                        "A15" to message.status,
                        "A07" to message.message_text.trim().toStupidString(),
                        "A118" to message.credential,
                        "A149" to message.attachment_flag.toString(),
                        "A52" to message.blog_id,
                        "ics" to message.consult.toString(),
                        "icc" to message.call_center.toString(),
                        "ccid" to message.call_center_id,
                        "iwm" to message.work_mode.toString(),
                        "Bf" to message.read_receipts.toString()
                    )
                    if (message.message_scope_id == "5") {
                        bodies["BR"] = message.f_display_name
                    }
                    if (message.contact.isNotEmpty()) {
                        bodies["A116"] = message.contact
                    }
                    if (message.image_id.isNotEmpty()) {
                        bodies["A57"] = message.image_id
                    }
                    if (message.audio_id.isNotEmpty()) {
                        bodies["A63"] = message.audio_id
                    }
                    if (message.video_id.isNotEmpty()) {
                        bodies["A47"] = message.video_id
                    }
                    if (message.file_id.isNotEmpty()) {
                        bodies["BN"] = message.file_id
                    }
                    if (message.thumb_id.isNotEmpty()) {
                        bodies["A74"] = message.thumb_id
                    }
                    if (message.reff_id.isNotEmpty()) {
                        bodies["A121"] = message.reff_id
                    }
                    if (message.chat_id.isNotEmpty()) {
                        bodies["BA"] = message.chat_id
                    }
                    if (message.broadcast_flag > 0) {
                        bodies["B4"] = message.broadcast_flag.toString()
                    }
                    val data = Data(
                        code = "S0",
                        status = message.message_id + System.nanoTime().toString(),
                        f_pin = message.f_pin,
                        bodies = bodies
                    )
                    val file = if (message.image_id.isNotEmpty()) message.image_id
                    else if (message.audio_id.isNotEmpty()) message.audio_id
                    else if (message.video_id.isNotEmpty()) message.video_id
                    else message.file_id
                    Log.d(tag, "message.file:$file")
                    if (file.isNotEmpty()) {
                        val upload = Network().upload(
                            "https://digixplatform.com/uploader",
                            File(context.filesDir, file)
                        )
                        if (!upload) {
                            Log.d(tag, "Failed to upload image:${message.message_id}")
                            return Result.retry()
                        }
                    }
                    Service.sendSync(data)?.let { r ->
                        return Result.success(
                            workDataOf(
                                "message_id" to r.bodies["A18"],
                                "opposite_pin" to r.bodies["A01"],
                                "status" to r.bodies["A15"]?.toInt()
                            )
                        )
                    }
                }
            }
        } catch (e: Exception) {
            return Result.failure()
        }
        return Result.retry()
    }

    private val notificationManager =
        context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    override suspend fun getForegroundInfo(): ForegroundInfo {
        val notificationId = 112345
        return ForegroundInfo(notificationId, createNotification())
    }

    private fun getString(@StringRes id: Int) = applicationContext.getString(id)

    private fun createNotification(): Notification {
        val channelId = getString(R.string.notification_channel_id)
        val title = getString(R.string.notification_title)
        val cancel = getString(R.string.cancel_processing)
        val name = getString(R.string.channel_name)
        // This PendingIntent can be used to cancel the Worker.
        val intent = WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)

        val builder = NotificationCompat.Builder(applicationContext, channelId)
            .setContentTitle(title)
            .setTicker(title)
            .setSmallIcon(applicationContext.applicationInfo.icon)
            .setOngoing(true)
            .addAction(R.drawable.baseline_cancel_24, cancel, intent)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel(channelId, name).also {
                builder.setChannelId(it.id)
            }
        }
        return builder.build()
    }

    @TargetApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(
        channelId: String,
        name: String
    ): NotificationChannel {
        return NotificationChannel(
            channelId, name, NotificationManager.IMPORTANCE_LOW
        ).also { channel ->
            notificationManager.createNotificationChannel(channel)
        }
    }
}