"""Tests for SYN Link crypto module — verifies cross-language compatibility."""

from syn_link.crypto import get_or_create_key_pair, encrypt_for_recipient, decrypt_from_sender


def test_encrypt_decrypt_roundtrip(tmp_path):
    """Test that messages can be encrypted and decrypted."""
    # Generate two key pairs (simulating two agents)
    sender_keys = get_or_create_key_pair(str(tmp_path / "sender"))
    recipient_keys = get_or_create_key_pair(str(tmp_path / "recipient"))

    message = "Hello from Python! 🐍"

    # Sender encrypts for recipient
    encrypted_content, nonce = encrypt_for_recipient(
        message, recipient_keys["publicKey"], sender_keys["secretKey"]
    )

    # Recipient decrypts
    plaintext = decrypt_from_sender(
        encrypted_content, nonce, sender_keys["publicKey"], recipient_keys["secretKey"]
    )

    assert plaintext == message


def test_different_messages_different_ciphertext(tmp_path):
    """Each encryption should produce different ciphertext (random nonce)."""
    sender_keys = get_or_create_key_pair(str(tmp_path / "sender"))
    recipient_keys = get_or_create_key_pair(str(tmp_path / "recipient"))

    msg = "test message"
    enc1, nonce1 = encrypt_for_recipient(msg, recipient_keys["publicKey"], sender_keys["secretKey"])
    enc2, nonce2 = encrypt_for_recipient(msg, recipient_keys["publicKey"], sender_keys["secretKey"])

    # Same plaintext should produce different ciphertext
    assert enc1 != enc2
    assert nonce1 != nonce2


def test_key_persistence(tmp_path):
    """Keys should be saved and reloaded consistently."""
    data_dir = str(tmp_path / "keys")
    keys1 = get_or_create_key_pair(data_dir)
    keys2 = get_or_create_key_pair(data_dir)

    assert keys1["publicKey"] == keys2["publicKey"]
    assert keys1["secretKey"] == keys2["secretKey"]


def test_wrong_key_fails(tmp_path):
    """Decryption with wrong key should fail."""
    sender_keys = get_or_create_key_pair(str(tmp_path / "sender"))
    recipient_keys = get_or_create_key_pair(str(tmp_path / "recipient"))
    wrong_keys = get_or_create_key_pair(str(tmp_path / "wrong"))

    message = "secret message"
    encrypted_content, nonce = encrypt_for_recipient(
        message, recipient_keys["publicKey"], sender_keys["secretKey"]
    )

    try:
        decrypt_from_sender(
            encrypted_content, nonce, sender_keys["publicKey"], wrong_keys["secretKey"]
        )
        assert False, "Should have raised an exception"
    except Exception:
        pass  # Expected


def test_empty_message(tmp_path):
    """Encryption handles empty strings correctly."""
    sender_keys = get_or_create_key_pair(str(tmp_path / "sender"))
    recipient_keys = get_or_create_key_pair(str(tmp_path / "recipient"))

    encrypted_content, nonce = encrypt_for_recipient(
        "", recipient_keys["publicKey"], sender_keys["secretKey"]
    )
    plaintext = decrypt_from_sender(
        encrypted_content, nonce, sender_keys["publicKey"], recipient_keys["secretKey"]
    )

    assert plaintext == ""


def test_unicode_and_emoji(tmp_path):
    """Encryption handles multibyte unicode and emoji correctly."""
    sender_keys = get_or_create_key_pair(str(tmp_path / "sender"))
    recipient_keys = get_or_create_key_pair(str(tmp_path / "recipient"))

    message = "שלום 🌍 こんにちは 🎉 مرحبا"
    encrypted_content, nonce = encrypt_for_recipient(
        message, recipient_keys["publicKey"], sender_keys["secretKey"]
    )
    plaintext = decrypt_from_sender(
        encrypted_content, nonce, sender_keys["publicKey"], recipient_keys["secretKey"]
    )

    assert plaintext == message


def test_large_message(tmp_path):
    """Encryption handles large messages (1MB)."""
    sender_keys = get_or_create_key_pair(str(tmp_path / "sender"))
    recipient_keys = get_or_create_key_pair(str(tmp_path / "recipient"))

    message = "x" * (1024 * 1024)  # 1MB
    encrypted_content, nonce = encrypt_for_recipient(
        message, recipient_keys["publicKey"], sender_keys["secretKey"]
    )
    plaintext = decrypt_from_sender(
        encrypted_content, nonce, sender_keys["publicKey"], recipient_keys["secretKey"]
    )

    assert plaintext == message

