package app.closer.crypto

import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Test

class AnswerCommitmentTest {

    private val subject = AnswerCommitment()

    @Test
    fun `same inputs produce same hash`() {
        val a = subject.compute("cpl1", "q1", "u1", "yes", listOf("a", "b"), 3)
        val b = subject.compute("cpl1", "q1", "u1", "yes", listOf("a", "b"), 3)
        assertEquals(a, b)
    }

    @Test
    fun `hash starts with sha256 prefix`() {
        val hash = subject.compute("cpl1", "q1", "u1", null, emptyList(), null)
        assertTrue(hash.startsWith(AnswerCommitment.PREFIX))
    }

    @Test
    fun `different writtenText produces different hash`() {
        val a = subject.compute("cpl1", "q1", "u1", "yes", emptyList(), null)
        val b = subject.compute("cpl1", "q1", "u1", "no", emptyList(), null)
        assertNotEquals(a, b)
    }

    @Test
    fun `different coupleId produces different hash`() {
        val a = subject.compute("cpl1", "q1", "u1", "hello", emptyList(), null)
        val b = subject.compute("cpl2", "q1", "u1", "hello", emptyList(), null)
        assertNotEquals(a, b)
    }

    @Test
    fun `selectedOptionIds order does not affect hash`() {
        val a = subject.compute("cpl1", "q1", "u1", null, listOf("x", "y"), null)
        val b = subject.compute("cpl1", "q1", "u1", null, listOf("y", "x"), null)
        assertEquals(a, b)
    }

    @Test
    fun `canonical JSON has fixed key order`() {
        val canon = subject.canonical("hello", listOf("b", "a"), 2)
        assertEquals(
            "{\"scaleValue\":2,\"selectedOptionIds\":[\"a\",\"b\"],\"writtenText\":\"hello\"}",
            canon
        )
    }

    @Test
    fun `canonical JSON handles null values`() {
        val canon = subject.canonical(null, emptyList(), null)
        assertEquals(
            "{\"scaleValue\":null,\"selectedOptionIds\":[],\"writtenText\":null}",
            canon
        )
    }

    @Test
    fun `canonical JSON escapes special characters`() {
        val canon = subject.canonical("say \"hi\"", emptyList(), null)
        assertTrue(canon.contains("say \\\"hi\\\""))
    }
}
