package wang.yaojia.webterm.hostregistry

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import wang.yaojia.webterm.wire.HostEndpoint
import java.util.UUID

/**
 * Instrumented (device) contract tests for [DataStoreHostStore] — the real
 * Preferences-DataStore-backed store needs a Context, so these run on a device
 * (no emulator in the build env → compiled here, executed in device QA, plan §7).
 * They assert the same read-modify-write / order-preserving behaviour the JVM
 * [InMemoryHostStoreTest] pins for the in-memory double.
 */
@RunWith(AndroidJUnit4::class)
class DataStoreHostStoreTest {

    private fun newStore(): DataStoreHostStore {
        val ctx = ApplicationProvider.getApplicationContext<Context>()
        val dataStore: DataStore<Preferences> = PreferenceDataStoreFactory.create(
            produceFile = { ctx.preferencesDataStoreFile("host-registry-test-${UUID.randomUUID()}") },
        )
        return DataStoreHostStore(dataStore)
    }

    private fun host(id: String, name: String = "host-$id", baseUrl: String = "http://10.0.0.1:3000") =
        Host(id = id, name = name, endpoint = requireNotNull(HostEndpoint.fromBaseUrl(baseUrl)))

    @Test
    fun upsert_persists_and_loadAll_reads_back() = runBlocking {
        val store = newStore()
        val a = host("1")

        assertEquals(listOf(a), store.upsert(a))
        assertEquals(listOf(a), store.loadAll())
    }

    @Test
    fun upsert_same_id_replaces_in_place() = runBlocking {
        val store = newStore()
        store.upsert(host("1"))
        val renamed = host("1", name = "renamed")

        assertEquals(listOf(renamed), store.upsert(renamed))
        assertEquals("renamed", store.loadAll().single().name)
    }

    @Test
    fun remove_unknown_is_noop() = runBlocking {
        val store = newStore()
        store.upsert(host("1"))

        assertEquals(1, store.remove("nope").size)
        assertEquals(0, store.remove("1").size)
        assertEquals(0, store.loadAll().size)
    }
}
