package wang.yaojia.webterm.api.models

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

/**
 * GitWrite payload + error decode (plan Phase A.3): each 200 payload decodes; a failure body
 * `{ok:false,error:"…"}` (git-ops) and `{error:"…"}` (worktrees) both yield the SAFE `error` string;
 * a garbled 200 body degrades to the payload defaults (never throws). The empty-sha commit case is
 * exercised (server can return `{ok:true, commit:""}`).
 */
class GitWriteTest {

    @Test
    fun `stage payload decodes staged and count`() {
        val r = decodeGitPayload("""{"ok":true,"staged":true,"count":3}""".toByteArray(), StageResult.serializer())
        assertEquals(StageResult(staged = true, count = 3), r)
    }

    @Test
    fun `commit payload decodes the sha and tolerates an empty sha`() {
        assertEquals("a1b2c3", decodeGitPayload("""{"ok":true,"commit":"a1b2c3"}""".toByteArray(), CommitResult.serializer()).commit)
        assertEquals("", decodeGitPayload("""{"ok":true,"commit":""}""".toByteArray(), CommitResult.serializer()).commit)
    }

    @Test
    fun `push payload decodes branch and remote`() {
        val r = decodeGitPayload("""{"ok":true,"branch":"main","remote":"origin"}""".toByteArray(), PushResult.serializer())
        assertEquals("main", r.branch)
        assertEquals("origin", r.remote)
    }

    @Test
    fun `worktree create and remove and prune payloads decode`() {
        val create = decodeGitPayload("""{"ok":true,"path":"/wt/x","branch":"feat"}""".toByteArray(), CreateWorktreeResult.serializer())
        assertEquals("/wt/x", create.path)
        assertEquals("feat", create.branch)

        val remove = decodeGitPayload("""{"ok":true,"path":"/wt/x"}""".toByteArray(), RemoveWorktreeResult.serializer())
        assertEquals("/wt/x", remove.path)

        val prune = decodeGitPayload("""{"ok":true,"pruned":["a","b"]}""".toByteArray(), PruneWorktreesResult.serializer())
        assertEquals(listOf("a", "b"), prune.pruned)
    }

    @Test
    fun `a garbled 200 body degrades to payload defaults, never throwing`() {
        assertEquals(StageResult(), decodeGitPayload("not json".toByteArray(), StageResult.serializer()))
        assertEquals(CommitResult(), decodeGitPayload("[]".toByteArray(), CommitResult.serializer()))
        assertTrue(decodeGitPayload("{}".toByteArray(), PruneWorktreesResult.serializer()).pruned.isEmpty())
    }

    @Test
    fun `a git-ops failure body yields the safe error string`() {
        assertEquals("Nothing to commit.", decodeGitError("""{"ok":false,"error":"Nothing to commit."}""".toByteArray()))
    }

    @Test
    fun `a worktree failure body (no ok field) still yields the error string`() {
        assertEquals("Worktree creation is disabled.", decodeGitError("""{"error":"Worktree creation is disabled."}""".toByteArray()))
    }

    @Test
    fun `an empty or errorless failure body yields null`() {
        assertNull(decodeGitError(ByteArray(0)))
        assertNull(decodeGitError("""{"ok":false}""".toByteArray()))
        assertNull(decodeGitError("not json".toByteArray()))
    }
}
