package swiss.qpq.gajumobile.security

import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Assume
import org.junit.Test
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import java.security.SecureRandom
import swiss.qpq.gajumaru.core.tools.TransactionService

class AccountAirlockTest {

    private fun assumeNativeLoaded() {
        Assume.assumeTrue("Native library failed to load: ${GajuNative.loadError}", GajuNative.loadError == null)
    }

    @Test
    fun testShortMnemonicRoundtrip() {
        // Create a "short" seed (first 4 bytes are zero)
        val seed = ByteArray(32)
        seed[0] = 0
        seed[1] = 0
        seed[2] = 0
        seed[3] = 0
        seed[4] = 0xFF.toByte() // Some data after zeros
        
        val phrase = swiss.qpq.gajumaru.core.encoding.Mnemonic.encode(seed)
        
        // A full 32-byte seed usually gives 23 words (1 checksum + 22 data).
        // With 4 leading zero bytes, we drop at least 2 chunks (32 bits / 12 bits = 2.66).
        assertTrue("Phrase should be shorter than 23 words", phrase.size < 23)
        
        val decoded = swiss.qpq.gajumaru.core.encoding.Mnemonic.decode(phrase)
        assertTrue("Decoded seed must match original short seed", seed.contentEquals(decoded))
        
        AccountAirlock.wipePhrase(phrase)
    }

    @Test
    fun testMnemonicRoundtrip() {
        // Let's test the roundtrip
        val entropy = ByteArray(32).apply { SecureRandom().nextBytes(this) }
        val phrase = swiss.qpq.gajumaru.core.encoding.Mnemonic.encode(entropy)
        val decoded = swiss.qpq.gajumaru.core.encoding.Mnemonic.decode(phrase)
        
        assertTrue(entropy.contentEquals(decoded))
        AccountAirlock.wipePhrase(phrase)
    }

    @Test
    fun testCreateAccountFlow() {
        assumeNativeLoaded()
        val keyGen = KeyGenerator.getInstance("AES")
        keyGen.init(256)
        val masterKey: SecretKey = keyGen.generateKey()
        
        val phrase = AccountAirlock.generateMnemonic()
        val account = AccountAirlock.createAccount("My Account", phrase, masterKey)
        
        assertNotNull(account)
        assertEquals("My Account", account.label)
        assertNotNull(account.publicKey)
        assertNotNull(account.privateKeyEnvelope)
        
        // Verify we can sign with this account
        val message = "Test sign".toByteArray()
        val signature = AccountAirlock.signBinary(account.privateKeyEnvelope, masterKey, message)
        
        assertNotNull(signature)
        assertTrue(TransactionService.verifyBinary(message, signature, account.publicKey))
        AccountAirlock.wipePhrase(phrase)
    }
}
