package com.tt.honeyDue.notifications

import android.app.AlarmManager
import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.Shadows.shadowOf
import org.robolectric.annotation.Config

/**
 * Tests for [SnoozeScheduler] — verifies the AlarmManager scheduling path
 * used by the P4 Stream O notification Snooze action.
 */
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.TIRAMISU])
class SnoozeSchedulerTest {

    private lateinit var context: Context
    private lateinit var am: AlarmManager

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
        am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        // Robolectric's ShadowAlarmManager doesn't have an explicit clear, but
        // scheduledAlarms is filtered by live pending intents so cancel() the
        // world before each test.
        shadowOf(am).scheduledAlarms.toList().forEach { alarm ->
            alarm.operation?.let { am.cancel(it) }
        }
    }

    // ---------- 7. schedule() sets alarm 30 minutes in future ----------

    @Test
    fun schedule_setsAlarmThirtyMinutesInFuture() {
        val before = System.currentTimeMillis()
        SnoozeScheduler.schedule(
            context = context,
            taskId = 123L,
            title = "t",
            body = "b",
            type = NotificationChannels.TASK_REMINDER
        )

        val scheduled = shadowOf(am).scheduledAlarms
        assertEquals(1, scheduled.size)
        val delta = scheduled.first().triggerAtTime - before
        val expected = NotificationActions.SNOOZE_DELAY_MS
        assertTrue(
            "expected ~30 min trigger, got delta=$delta",
            delta in (expected - 2_000)..(expected + 2_000)
        )
    }

    // ---------- 8. cancel() removes the pending alarm ----------

    @Test
    fun cancel_preventsLaterDelivery() {
        SnoozeScheduler.schedule(context, taskId = 456L)
        assertEquals(
            "precondition: alarm scheduled",
            1,
            shadowOf(am).scheduledAlarms.size
        )

        SnoozeScheduler.cancel(context, taskId = 456L)

        // After cancel(), the PendingIntent is consumed so scheduledAlarms
        // shrinks back to zero (Robolectric matches by PI equality).
        assertEquals(
            "alarm should be gone after cancel()",
            0,
            shadowOf(am).scheduledAlarms.size
        )
    }

    // Bonus coverage: different task ids get independent scheduling slots.
    @Test
    fun schedule_twoDifferentTasks_yieldsTwoAlarms() {
        SnoozeScheduler.schedule(context, taskId = 1L)
        SnoozeScheduler.schedule(context, taskId = 2L)
        assertEquals(2, shadowOf(am).scheduledAlarms.size)
    }
}
