import { bytesToHex, hexToBytes, randomBytes } from '@noble/hashes/utils'
import { secp256k1 } from '@noble/curves/secp256k1'
import { cbc } from '@noble/ciphers/aes'
import { base64 } from '@scure/base'

// UTF-8 encoder/decoder
const utf8Encoder = new TextEncoder()
const utf8Decoder = new TextDecoder()

function getNormalizedX(key) {
    return key.slice(1, 33)
}

function encrypt(secretKey, pubkey, text) {
    console.log(`[JS] Encrypting "${text}" using sk1 -> pk2`)
    console.log(`[JS] Private Key: ${secretKey}`)
    console.log(`[JS] Public Key:  ${pubkey}`)
    
    // Step 1: Get shared secret
    const key = secp256k1.getSharedSecret(secretKey, '02' + pubkey)
    console.log(`[JS] Shared Secret: ${bytesToHex(key)}`)
    
    // Step 2: Normalize key (remove first byte, keep next 32)
    const normalizedKey = getNormalizedX(key)
    console.log(`[JS] Normalized Key: ${bytesToHex(normalizedKey)}`)
    
    // Step 3: Generate random IV
    const iv = randomBytes(16)
    console.log(`[JS] IV: ${bytesToHex(iv)}`)
    
    // Step 4: Encode plaintext to UTF-8
    const plaintext = utf8Encoder.encode(text)
    console.log(`[JS] UTF-8 Plaintext: ${bytesToHex(plaintext)}`)
    
    // Step 5: AES-CBC encryption
    const ciphertext = cbc(normalizedKey, iv).encrypt(plaintext)
    console.log(`[JS] Raw Ciphertext: ${bytesToHex(new Uint8Array(ciphertext))}`)
    
    // Step 6: Base64 encoding
    const ctb64 = base64.encode(new Uint8Array(ciphertext))
    const ivb64 = base64.encode(new Uint8Array(iv.buffer))
    
    const result = `${ctb64}?iv=${ivb64}`
    console.log(`[JS] Encrypted Result: ${result}`)
    
    return result
}

function decrypt(secretKey, pubkey, data) {
    console.log(`[JS] Decrypting "${data}" using sk2 + pk1`)
    console.log(`[JS] Private Key: ${secretKey}`)
    console.log(`[JS] Public Key:  ${pubkey}`)
    
    // Step 1: Parse format
    const [ctb64, ivb64] = data.split('?iv=')
    
    // Step 2: Get shared secret
    const key = secp256k1.getSharedSecret(secretKey, '02' + pubkey)
    console.log(`[JS] Shared Secret: ${bytesToHex(key)}`)
    
    // Step 3: Normalize key
    const normalizedKey = getNormalizedX(key)
    console.log(`[JS] Normalized Key: ${bytesToHex(normalizedKey)}`)
    
    // Step 4: Base64 decode
    const iv = base64.decode(ivb64)
    const ciphertext = base64.decode(ctb64)
    console.log(`[JS] IV: ${bytesToHex(iv)}`)
    console.log(`[JS] Raw Ciphertext: ${bytesToHex(ciphertext)}`)
    
    // Step 5: AES-CBC decryption
    const plaintext = cbc(normalizedKey, iv).decrypt(ciphertext)
    console.log(`[JS] Decrypted Plaintext: ${bytesToHex(plaintext)}`)
    
    // Step 6: UTF-8 decode
    const result = utf8Decoder.decode(plaintext)
    console.log(`[JS] UTF-8 Decoded: "${result}"`)
    
    return result
}

// Test with exact vectors
async function main() {
    console.log("=== NIP-04 DEBUG COMPARISON (JavaScript) ===")
    
    const sk1 = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe"
    const pk1 = "b38ce15d3d9874ee710dfabb7ff9801b1e0e20aace6e9a1a05fa7482a04387d1"
    const sk2 = "96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220"
    const pk2 = "dcb33a629560280a0ee3b6b99b68c044fe8914ad8a984001ebf6099a9b474dc3"
    const plaintext = "nanana"
    const expectedCiphertext = "d6Joav5EciPI9hdHw31vmQ==?iv=fWs5rfv2+532arG/k83kcA=="
    
    console.log("\n--- ENCRYPTION TEST ---")
    const encrypted = encrypt(sk1, pk2, plaintext)
    
    console.log("\n--- DECRYPTION TEST ---")
    const decrypted = decrypt(sk2, pk1, expectedCiphertext)
    
    console.log("\n--- RESULTS ---")
    console.log(`Encryption Success: Generated ciphertext`)
    console.log(`Decryption Success: ${decrypted === plaintext}`)
    console.log(`Expected: "${plaintext}"`)
    console.log(`Got:      "${decrypted}"`)
}

main().catch(console.error)
