package ani.dantotsu.notifications.subscription

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import ani.dantotsu.App
import ani.dantotsu.FileUrl
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.UrlMedia
import ani.dantotsu.hasNotificationPermission
import ani.dantotsu.notifications.Task
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.parsers.Episode
import ani.dantotsu.parsers.MangaChapter
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.util.Logger
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK
import eu.kanade.tachiyomi.data.notification.Notifications.CHANNEL_SUBSCRIPTION_CHECK_PROGRESS
import eu.kanade.tachiyomi.data.notification.Notifications.ID_SUBSCRIPTION_CHECK_PROGRESS
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


class SubscriptionNotificationTask : Task {
    private var currentlyPerforming = false

    @SuppressLint("MissingPermission")
    override suspend fun execute(context: Context): Boolean {
        if (!currentlyPerforming) {
            try {
                withContext(Dispatchers.IO) {
                    PrefManager.init(context)
                    currentlyPerforming = true
                    App.context = context
                    Logger.log("SubscriptionNotificationTask: execute")
                    var timeout = 15_000L
                    do {
                        delay(1000)
                        timeout -= 1000
                    } while (timeout > 0 && !AnimeSources.isInitialized && !MangaSources.isInitialized)
                    Logger.log("SubscriptionNotificationTask: timeout: $timeout")
                    if (timeout <= 0) {
                        currentlyPerforming = false
                        return@withContext
                    }
                    val subscriptions = SubscriptionHelper.getSubscriptions()
                    var i = 0
                    val index = subscriptions.map { i++; it.key to i }.toMap()
                    val notificationManager = NotificationManagerCompat.from(context)

                    val progressEnabled: Boolean =
                        PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
                    val progressNotification = if (progressEnabled) getProgressNotification(
                        context,
                        subscriptions.size
                    ) else null
                    if (progressNotification != null && hasNotificationPermission(context)) {
                        notificationManager.notify(
                            ID_SUBSCRIPTION_CHECK_PROGRESS,
                            progressNotification.build()
                        )
                        //Seems like if the parent coroutine scope gets cancelled, the notification stays
                        //So adding this as a safeguard? dk if this will be useful
                        CoroutineScope(Dispatchers.Main).launch {
                            delay(5 * subscriptions.size * 1000L)
                            notificationManager.cancel(ID_SUBSCRIPTION_CHECK_PROGRESS)
                        }
                    }

                    fun progress(progress: Int, parser: String, media: String) {
                        if (progressNotification != null && hasNotificationPermission(context))
                            notificationManager.notify(
                                ID_SUBSCRIPTION_CHECK_PROGRESS,
                                progressNotification
                                    .setProgress(subscriptions.size, progress, false)
                                    .setContentText("$media on $parser")
                                    .build()
                            )
                    }

                    subscriptions.toList().map {
                        val media = it.second
                        val text = if (media.isAnime) {
                            val parser =
                                SubscriptionHelper.getAnimeParser(media.id)
                            progress(index[it.first]!!, parser.name, media.name)
                            val ep: Episode? =
                                SubscriptionHelper.getEpisode(
                                    parser,
                                    media.id
                                )
                            if (ep != null) context.getString(R.string.episode) + "${ep.number}${
                                if (ep.title != null) " : ${ep.title}" else ""
                            }${
                                if (ep.isFiller) " [Filler]" else ""
                            } " + context.getString(R.string.just_released) to ep.thumbnail
                            else null
                        } else {
                            val parser =
                                SubscriptionHelper.getMangaParser(media.id)
                            progress(index[it.first]!!, parser.name, media.name)
                            val ep: MangaChapter? =
                                SubscriptionHelper.getChapter(
                                    parser,
                                    media.id
                                )
                            if (ep != null) ep.number + " " + context.getString(R.string.just_released) to null
                            else null
                        } ?: return@map
                        val notification = createNotification(
                            context.applicationContext,
                            media,
                            text.first,
                            text.second
                        )
                        if (hasNotificationPermission(context)) {
                            NotificationManagerCompat.from(context)
                                .notify(
                                    CHANNEL_SUBSCRIPTION_CHECK,
                                    System.currentTimeMillis().toInt(),
                                    notification
                                )
                        }
                    }

                    if (progressNotification != null) notificationManager.cancel(
                        ID_SUBSCRIPTION_CHECK_PROGRESS
                    )
                    currentlyPerforming = false
                }
                return true
            } catch (e: Exception) {
                Logger.log("SubscriptionNotificationTask: ${e.message}")
                Logger.log(e)
                return false
            }
        } else {
            return false
        }
    }

    @SuppressLint("MissingPermission")
    private fun createNotification(
        context: Context,
        media: SubscriptionHelper.Companion.SubscribeMedia,
        text: String,
        thumbnail: FileUrl?
    ): android.app.Notification {
        val pendingIntent = getIntent(context, media.id)
        val icon =
            if (media.isAnime) R.drawable.ic_round_movie_filter_24 else R.drawable.ic_round_menu_book_24

        val builder = NotificationCompat.Builder(context, CHANNEL_SUBSCRIPTION_CHECK)
            .setSmallIcon(icon)
            .setContentTitle(media.name)
            .setContentText(text)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)

        if (thumbnail != null) {
            val bitmap = getBitmapFromUrl(thumbnail.url)
            if (bitmap != null) {
                builder.setLargeIcon(bitmap)
            }
        }

        return builder.build()

    }

    private fun getProgressNotification(
        context: Context,
        size: Int
    ): NotificationCompat.Builder {
        return NotificationCompat.Builder(context, CHANNEL_SUBSCRIPTION_CHECK_PROGRESS)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle(context.getString(R.string.checking_subscriptions_title))
            .setProgress(size, 0, false)
            .setOngoing(true)
            .setAutoCancel(false)
    }

    private fun getBitmapFromUrl(url: String): Bitmap? {
        return try {
            val inputStream = java.net.URL(url).openStream()
            BitmapFactory.decodeStream(inputStream)
        } catch (e: Exception) {
            null
        }
    }


    private fun getIntent(context: Context, mediaId: Int): PendingIntent {
        val notifyIntent = Intent(context, UrlMedia::class.java)
            .putExtra("media", mediaId)
            .setAction(mediaId.toString())
            .apply {
                flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            }
        return PendingIntent.getActivity(
            context, mediaId, notifyIntent,
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_ONE_SHOT
            } else {
                PendingIntent.FLAG_ONE_SHOT
            }
        )
    }
}