package com.tt.honeyDue.widget

import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import androidx.work.Configuration
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.testing.WorkManagerTestInitHelper
import kotlinx.coroutines.runBlocking
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.annotation.Config

/**
 * Tests for [WidgetUpdateManager] using WorkManager's in-memory test
 * infrastructure.
 */
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.TIRAMISU])
class WidgetUpdateManagerTest {

    private lateinit var context: Context
    private lateinit var workManager: WorkManager

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
        val config = Configuration.Builder()
            .setMinimumLoggingLevel(android.util.Log.DEBUG)
            .build()
        WorkManagerTestInitHelper.initializeTestWorkManager(context, config)
        workManager = WorkManager.getInstance(context)
    }

    @Test
    fun schedulePeriodic_enqueues_unique_work() = runBlocking {
        WidgetUpdateManager.schedulePeriodic(context)

        val infos = workManager
            .getWorkInfosForUniqueWork(WidgetUpdateManager.UNIQUE_WORK_NAME)
            .get()

        assertEquals(1, infos.size)
        val state = infos.first().state
        assertTrue(
            "Expected ENQUEUED or RUNNING, got $state",
            state == WorkInfo.State.ENQUEUED || state == WorkInfo.State.RUNNING
        )
    }

    @Test
    fun schedulePeriodic_twice_replaces_work() = runBlocking {
        WidgetUpdateManager.schedulePeriodic(context)
        val firstInfos = workManager
            .getWorkInfosForUniqueWork(WidgetUpdateManager.UNIQUE_WORK_NAME)
            .get()
        val firstId = firstInfos.first().id

        WidgetUpdateManager.schedulePeriodic(context)
        val secondInfos = workManager
            .getWorkInfosForUniqueWork(WidgetUpdateManager.UNIQUE_WORK_NAME)
            .get()

        // With REPLACE policy, only one active entry remains; the old id may
        // linger briefly in CANCELLED state but the active id is new.
        val activeSecond = secondInfos.filter {
            it.state != WorkInfo.State.CANCELLED && it.state != WorkInfo.State.SUCCEEDED
        }
        assertEquals(1, activeSecond.size)
        assertTrue(
            "REPLACE should have enqueued a new work id",
            activeSecond.first().id != firstId
        )
    }

    @Test
    fun forceRefresh_enqueues_separate_unique_work() = runBlocking {
        WidgetUpdateManager.forceRefresh(context)

        val infos = workManager
            .getWorkInfosForUniqueWork(WidgetUpdateManager.FORCE_REFRESH_WORK_NAME)
            .get()

        assertEquals(1, infos.size)
        val state = infos.first().state
        assertTrue(
            "Expected ENQUEUED or RUNNING, got $state",
            state == WorkInfo.State.ENQUEUED || state == WorkInfo.State.RUNNING
        )
    }

    @Test
    fun cancel_removes_scheduled_work() = runBlocking {
        WidgetUpdateManager.schedulePeriodic(context)
        WidgetUpdateManager.cancel(context)

        val infos = workManager
            .getWorkInfosForUniqueWork(WidgetUpdateManager.UNIQUE_WORK_NAME)
            .get()

        val active = infos.filter {
            it.state == WorkInfo.State.ENQUEUED || it.state == WorkInfo.State.RUNNING
        }
        assertTrue("No active work should remain after cancel", active.isEmpty())
    }
}
