package com.correx.apps.server.memory

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.attribute.FileTime

class WorkspaceStateProbeTest {

    private val probe = RealWorkspaceStateProbe()

    @Test
    fun `non-git dir with kt files produces fingerprint state`(@TempDir dir: Path) {
        Files.writeString(dir.resolve("Main.kt"), "fun main() {}")
        Files.writeString(dir.resolve("Foo.kt"), "class Foo")

        val state = probe.observe(dir.toString())

        assertNotNull(state)
        assertTrue(state!!.stateKey.startsWith("fp:"), "stateKey should start with fp: but was ${state.stateKey}")
        assertEquals("fingerprint", state.source)
        assertNull(state.branch)
        assertEquals(false, state.dirty)
    }

    @Test
    fun `fingerprint is deterministic across two calls`(@TempDir dir: Path) {
        Files.writeString(dir.resolve("Main.kt"), "fun main() {}")

        val s1 = probe.observe(dir.toString())
        val s2 = probe.observe(dir.toString())

        assertNotNull(s1)
        assertNotNull(s2)
        assertEquals(s1!!.stateKey, s2!!.stateKey)
    }

    @Test
    fun `changing a file mtime changes the fingerprint`(@TempDir dir: Path) {
        val file = dir.resolve("Main.kt")
        Files.writeString(file, "fun main() {}")

        val s1 = probe.observe(dir.toString())
        assertNotNull(s1)

        Files.setLastModifiedTime(file, FileTime.fromMillis(System.currentTimeMillis() + 5_000L))

        val s2 = probe.observe(dir.toString())
        assertNotNull(s2)

        assertNotEquals(s1!!.stateKey, s2!!.stateKey, "fingerprint should change when mtime changes")
    }

    @Test
    fun `nonexistent root returns null`() {
        val result = probe.observe("/no/such/path/correx-probe-test")
        assertNull(result)
    }
}
