package pl.firmatpp.kierowca.sync

import android.Manifest
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.work.CoroutineWorker
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import pl.firmatpp.kierowca.MainActivity
import pl.firmatpp.kierowca.R

class LeaveRequestDecisionNotificationWorker(
    appContext: Context,
    params: WorkerParameters,
) : CoroutineWorker(appContext, params) {
    override suspend fun doWork(): Result {
        val leaveRequestId = inputData.getString(KEY_LEAVE_REQUEST_ID)?.takeIf(String::isNotBlank)
            ?: return Result.success()

        if (!canShowNotifications(applicationContext)) {
            return Result.success()
        }

        createChannel(applicationContext)
        val title = inputData.getString(KEY_TITLE)?.takeIf(String::isNotBlank) ?: "Decyzja w sprawie urlopu"
        val body = inputData.getString(KEY_BODY)?.takeIf(String::isNotBlank) ?: "Status wniosku urlopowego został zmieniony."
        val intent = Intent(applicationContext, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
            putExtra(MainActivity.EXTRA_LEAVE_REQUEST_ID, leaveRequestId)
        }
        val pendingIntent = PendingIntent.getActivity(
            applicationContext,
            leaveRequestId.hashCode(),
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
        )

        val notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(body)
            .setStyle(NotificationCompat.BigTextStyle().bigText(body))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setCategory(NotificationCompat.CATEGORY_STATUS)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .build()

        NotificationManagerCompat.from(applicationContext).notify(leaveRequestId.hashCode(), notification)
        return Result.success()
    }

    private fun createChannel(context: Context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return

        val channel = NotificationChannel(
            CHANNEL_ID,
            "Wnioski urlopowe",
            NotificationManager.IMPORTANCE_DEFAULT,
        ).apply {
            description = "Powiadomienia o decyzjach w sprawie wniosków urlopowych."
        }
        context.getSystemService(NotificationManager::class.java)?.createNotificationChannel(channel)
    }

    private fun canShowNotifications(context: Context): Boolean {
        val hasRuntimePermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU ||
            ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED

        return hasRuntimePermission && NotificationManagerCompat.from(context).areNotificationsEnabled()
    }

    companion object {
        private const val CHANNEL_ID = "leave_request_decisions"
        private const val KEY_LEAVE_REQUEST_ID = "leaveRequestId"
        private const val KEY_TITLE = "title"
        private const val KEY_BODY = "body"

        fun enqueue(context: Context, leaveRequestId: String?, title: String?, body: String?) {
            if (leaveRequestId.isNullOrBlank()) return

            val request = OneTimeWorkRequestBuilder<LeaveRequestDecisionNotificationWorker>()
                .setInputData(
                    workDataOf(
                        KEY_LEAVE_REQUEST_ID to leaveRequestId,
                        KEY_TITLE to title,
                        KEY_BODY to body,
                    ),
                )
                .build()

            WorkManager.getInstance(context).enqueueUniqueWork(
                "driver-leave-request-decision-$leaveRequestId",
                ExistingWorkPolicy.REPLACE,
                request,
            )
        }
    }
}
