package dev.privacyllc.period.lock

import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.flow.first
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

/**
 * The session flag, and the parked notification action.
 *
 * Pure Kotlin — no Robolectric, no Android. The controller holds no Android
 * types precisely so this can be true.
 */
class AppLockControllerTest {

    @Test fun `a new process starts locked`() = runBlocking {
        assertFalse(
            "a cold start must never begin unlocked — that is the whole reason " +
                "this is not saved state",
            AppLockController().unlocked.first(),
        )
    }

    @Test fun `unlock and lock move the flag`() = runBlocking {
        val controller = AppLockController()
        controller.unlock()
        assertTrue(controller.unlocked.first())
        controller.lock()
        assertFalse(controller.unlocked.first())
    }

    /**
     * Tapping "Not yet" on a reminder writes to the health record, and that
     * button sits on the phone's own lock screen where anybody can reach it. The
     * action is therefore parked, not applied, until somebody authenticates.
     */
    @Test fun `a notification action is held rather than applied`() = runBlocking {
        val controller = AppLockController()
        controller.holdNotificationAction("not_yet")

        assertEquals("not_yet", controller.pendingNotificationAction.first())
        assertEquals("not_yet", controller.takeNotificationAction())
    }

    @Test fun `taking the action consumes it, so it cannot be applied twice`() {
        val controller = AppLockController()
        controller.holdNotificationAction("not_yet")

        assertEquals("not_yet", controller.takeNotificationAction())
        assertNull("a second take must find nothing", controller.takeNotificationAction())
    }

    @Test fun `holding null does not clear an action already waiting`() {
        val controller = AppLockController()
        controller.holdNotificationAction("started")
        // Every launch delivers an intent; most carry no action. That must not
        // discard one that is genuinely waiting.
        controller.holdNotificationAction(null)
        assertEquals("started", controller.takeNotificationAction())
    }

    @Test fun `the auth-in-progress flag defaults to false`() {
        assertFalse(AppLockController().authInProgress)
    }
}
