package com.applemand.zmanim.core.notifications

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.content.getSystemService
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.Calendar
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ZmanimAlarmScheduler @Inject constructor(
    @ApplicationContext private val context: Context,
) {

    fun schedulePeriodicDaily(hour: Int = 8, minute: Int = 0) {
        val now = Calendar.getInstance()
        val target = Calendar.getInstance().apply {
            set(Calendar.HOUR_OF_DAY, hour); set(Calendar.MINUTE, minute)
            set(Calendar.SECOND, 0); set(Calendar.MILLISECOND, 0)
            if (before(now)) add(Calendar.DAY_OF_YEAR, 1)
        }
        val initialDelayMs = target.timeInMillis - now.timeInMillis

        val req = PeriodicWorkRequestBuilder<DailyZmanimWorker>(1, TimeUnit.DAYS)
            .setInitialDelay(initialDelayMs, TimeUnit.MILLISECONDS)
            .setConstraints(Constraints.Builder().build())
            .build()
        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            WORK_DAILY, ExistingPeriodicWorkPolicy.UPDATE, req
        )
    }

    fun scheduleExact(
        triggerAtMs: Long,
        id: Int,
        title: String,
        text: String,
    ) {
        val am = context.getSystemService<AlarmManager>() ?: return
        val intent = Intent(context, ZmanimAlarmReceiver::class.java).apply {
            putExtra(ZmanimAlarmReceiver.KEY_TITLE, title)
            putExtra(ZmanimAlarmReceiver.KEY_TEXT, text)
            putExtra(ZmanimAlarmReceiver.KEY_ID, id)
        }
        val pi = PendingIntent.getBroadcast(
            context, id, intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )
        val canExact = Build.VERSION.SDK_INT < Build.VERSION_CODES.S || am.canScheduleExactAlarms()
        if (canExact) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMs, pi)
        } else {
            am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMs, pi)
        }
    }

    fun cancel(id: Int) {
        val am = context.getSystemService<AlarmManager>() ?: return
        val intent = Intent(context, ZmanimAlarmReceiver::class.java)
        val pi = PendingIntent.getBroadcast(
            context, id, intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE
        )
        if (pi != null) am.cancel(pi)
    }

    companion object {
        const val WORK_DAILY = "luach.work.daily"
    }
}
