package wang.yaojia.webterm.api.models

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

/**
 * GitLogResult list-lossy decode (plan Phase A.2): a well-formed `{commits,truncated}` decodes; a
 * commit missing `hash`/`at` is dropped while its siblings survive; `truncated` passes through; a
 * subject-less commit still decodes (subject defaults to empty).
 */
class GitLogTest {

    private fun decode(json: String): GitLogResult? =
        LossyDecode.objectOrNull(json.toByteArray(), GitLogResult.serializer())

    @Test
    fun `decodes commits and truncated`() {
        val json = """
          { "truncated": true, "commits": [
            { "hash":"abc123", "at": 1710000000000, "subject":"first" },
            { "hash":"def456", "at": 1710000005000, "subject":"second" }
          ] }
        """.trimIndent()

        val result = decode(json)!!
        assertTrue(result.truncated)
        assertEquals(2, result.commits.size)
        assertEquals("abc123", result.commits[0].hash)
        assertEquals(1710000000000L, result.commits[0].at)
        assertEquals("first", result.commits[0].subject)
    }

    @Test
    fun `drops a commit missing hash or at, keeping the rest`() {
        val json = """
          { "truncated": false, "commits": [
            { "at": 1, "subject":"no hash" },
            { "hash":"keep", "at": 2, "subject":"kept" },
            { "hash":"noAt", "subject":"no at" }
          ] }
        """.trimIndent()

        val result = decode(json)!!
        assertFalse(result.truncated)
        assertEquals(1, result.commits.size)
        assertEquals("keep", result.commits.single().hash)
    }

    @Test
    fun `a subject-less commit still decodes with an empty subject`() {
        val result = decode("""{ "commits":[ { "hash":"h", "at": 5 } ] }""")!!
        assertEquals(1, result.commits.size)
        assertEquals("", result.commits.single().subject)
        assertFalse(result.truncated) // default
    }

    @Test
    fun `a non-object body degrades to null`() {
        org.junit.jupiter.api.Assertions.assertNull(decode("[]"))
        org.junit.jupiter.api.Assertions.assertNull(decode("garbage"))
    }
}
