/**
 * Тест совместимости Android crypto с crypto_new (JavaScript)
 * 
 * Этот файл проверяет, что Android и JavaScript генерируют одинаковые ключи
 * из одинаковой seed phrase.
 * 
 * Для запуска теста:
 * 1. Запустите этот тест в Android приложении
 * 2. Скопируйте seed phrase из логов
 * 3. Запустите test-crypto-new-compat.js с той же seed phrase
 * 4. Сравните результаты - они должны совпадать!
 */

package com.rosetta.messenger.crypto

import org.junit.Test
import org.junit.Assert.*
import java.security.Security
import org.bouncycastle.jce.provider.BouncyCastleProvider

class CryptoNewCompatibilityTest {
    
    init {
        // Добавляем BouncyCastle provider
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(BouncyCastleProvider())
        }
    }
    
    @Test
    fun testKeyGenerationFromFixedSeedPhrase() {
        // Фиксированная seed phrase для тестирования
        val seedPhrase = listOf(
            "abandon", "abandon", "abandon", "abandon", "abandon", "abandon",
            "abandon", "abandon", "abandon", "abandon", "abandon", "about"
        )
        
        println("=== Crypto New Compatibility Test ===")
        println("Seed phrase: ${seedPhrase.joinToString(" ")}")
        println()
        
        // Генерируем ключи
        val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
        val privateKeyHash = CryptoManager.generatePrivateKeyHash(keyPair.privateKey)
        
        // Выводим результаты
        println("Android Results:")
        println("Private Key: ${keyPair.privateKey}")
        println("Public Key:  ${keyPair.publicKey}")
        println("Private Key Hash: $privateKeyHash")
        println()
        
        // Проверяем формат
        assertEquals("Private key should be 64 hex chars (32 bytes)", 64, keyPair.privateKey.length)
        assertEquals("Public key should be 66 hex chars (33 bytes compressed)", 66, keyPair.publicKey.length)
        assertEquals("Private key hash should be 64 hex chars", 64, privateKeyHash.length)
        
        // Проверяем что публичный ключ сжатый (начинается с 02 или 03)
        assertTrue(
            "Public key should start with 02 or 03 (compressed format)",
            keyPair.publicKey.startsWith("02") || keyPair.publicKey.startsWith("03")
        )
        
        println("✅ Format checks passed!")
        println()
        println("Now run this in JavaScript (crypto_new/crypto.ts):")
        println("```javascript")
        println("const { generateKeyPairFromSeed, generateHashFromPrivateKey } = require('./crypto');")
        println("const seedPhrase = '${seedPhrase.joinToString(" ")}';")
        println("const keyPair = await generateKeyPairFromSeed(seedPhrase);")
        println("const hash = await generateHashFromPrivateKey(keyPair.privateKey);")
        println("console.log('Private Key:', keyPair.privateKey);")
        println("console.log('Public Key:', keyPair.publicKey);")
        println("console.log('Hash:', hash);")
        println("```")
        println()
        println("Expected JavaScript results:")
        println("Private Key: ${keyPair.privateKey}")
        println("Public Key:  ${keyPair.publicKey}")
        println("Hash: $privateKeyHash")
    }
    
    @Test
    fun testMultipleSeedPhrases() {
        val testCases = listOf(
            listOf("test", "seed", "phrase", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"),
            listOf("hello", "world", "crypto", "test", "android", "kotlin", "secp256k1", "sha256", "compressed", "public", "key", "format"),
            listOf("abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "about")
        )
        
        println("=== Multiple Seed Phrases Test ===")
        
        testCases.forEachIndexed { index, seedPhrase ->
            println("Test case ${index + 1}:")
            println("Seed: ${seedPhrase.joinToString(" ")}")
            
            val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
            val hash = CryptoManager.generatePrivateKeyHash(keyPair.privateKey)
            
            println("Private: ${keyPair.privateKey}")
            println("Public:  ${keyPair.publicKey}")
            println("Hash:    $hash")
            
            // Verify format
            assertEquals(64, keyPair.privateKey.length)
            assertEquals(66, keyPair.publicKey.length)
            assertTrue(keyPair.publicKey.startsWith("02") || keyPair.publicKey.startsWith("03"))
            
            println("✅ Passed")
            println()
        }
    }
    
    @Test
    fun testPrivateKeyHashGeneration() {
        val privateKey = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
        val hash = CryptoManager.generatePrivateKeyHash(privateKey)
        
        println("=== Private Key Hash Test ===")
        println("Private Key: $privateKey")
        println("Hash (Android): $hash")
        println()
        println("JavaScript equivalent:")
        println("```javascript")
        println("const privateKey = '$privateKey';")
        println("const hash = sha256.create().update(privateKey + 'rosetta').digest().toHex().toString();")
        println("console.log('Hash (JS):', hash);")
        println("```")
        println()
        println("Hashes should match!")
        
        assertEquals(64, hash.length)
    }
    
    @Test
    fun testPublicKeyCompression() {
        // Тестируем что все публичные ключи действительно сжаты
        val seedPhrases = listOf(
            listOf("word", "word", "word", "word", "word", "word", "word", "word", "word", "word", "word", "word"),
            listOf("test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test"),
            listOf("crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto", "crypto")
        )
        
        println("=== Public Key Compression Test ===")
        
        seedPhrases.forEach { seedPhrase ->
            val keyPair = CryptoManager.generateKeyPairFromSeed(seedPhrase)
            
            // Проверяем что ключ сжатый (33 байта = 66 hex chars)
            assertEquals("Public key must be compressed (33 bytes)", 66, keyPair.publicKey.length)
            
            // Проверяем префикс (02 для четного Y, 03 для нечетного Y)
            val prefix = keyPair.publicKey.substring(0, 2)
            assertTrue(
                "Compressed public key must start with 02 or 03",
                prefix == "02" || prefix == "03"
            )
            
            println("✅ ${seedPhrase.joinToString(" ")}: ${keyPair.publicKey}")
        }
        
        println()
        println("✅ All public keys are compressed!")
    }
    
    @Test
    fun testCachingMechanism() {
        val seedPhrase = listOf("cache", "test", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten")
        
        println("=== Caching Test ===")
        
        // Первый вызов - генерация
        val start1 = System.currentTimeMillis()
        val keyPair1 = CryptoManager.generateKeyPairFromSeed(seedPhrase)
        val time1 = System.currentTimeMillis() - start1
        
        // Второй вызов - из кэша
        val start2 = System.currentTimeMillis()
        val keyPair2 = CryptoManager.generateKeyPairFromSeed(seedPhrase)
        val time2 = System.currentTimeMillis() - start2
        
        println("First call (generation): ${time1}ms")
        println("Second call (from cache): ${time2}ms")
        println("Speedup: ${time1.toFloat() / time2.toFloat()}x")
        
        // Проверяем что результаты идентичны
        assertEquals(keyPair1.privateKey, keyPair2.privateKey)
        assertEquals(keyPair1.publicKey, keyPair2.publicKey)
        
        println("✅ Cache is working correctly!")
    }
}
