"""
Irene Cipher - Python Examples

This file demonstrates all the features of the irene_cipher library.
"""

import irene_cipher
import os
from pathlib import Path


def example_text_encryption():
    """Example: Encrypting and decrypting text"""
    print("=" * 60)
    print("Example 1: Text Encryption")
    print("=" * 60)
    
    password = "my_secure_password_2024!"
    plaintext = "Hello, World! This is a secret message."
    
    print(f"Plaintext: {plaintext}")
    print(f"Password: {password}")
    
    # Encrypt
    ciphertext = irene_cipher.encrypt_text(plaintext, password)
    print(f"\nEncrypted ({len(ciphertext)} bytes): {ciphertext.hex()[:64]}...")
    
    # Decrypt
    decrypted = irene_cipher.decrypt_text(ciphertext, password)
    print(f"Decrypted: {decrypted}")
    
    assert decrypted == plaintext
    print("✓ Text encryption/decryption successful!\n")


def example_binary_encryption():
    """Example: Encrypting and decrypting binary data"""
    print("=" * 60)
    print("Example 2: Binary Data Encryption")
    print("=" * 60)
    
    password = "binary_data_password"
    
    # Create some binary data
    original_data = bytes([i % 256 for i in range(1000)])
    print(f"Original data ({len(original_data)} bytes): {original_data[:20].hex()}...")
    
    # Encrypt
    encrypted = irene_cipher.encrypt_bytes(original_data, password)
    print(f"Encrypted ({len(encrypted)} bytes): {encrypted[:20].hex()}...")
    
    # Decrypt
    decrypted = irene_cipher.decrypt_bytes(encrypted, password)
    print(f"Decrypted ({len(decrypted)} bytes): {decrypted[:20].hex()}...")
    
    assert decrypted == original_data
    print("✓ Binary encryption/decryption successful!\n")


def example_file_encryption():
    """Example: Encrypting and decrypting files"""
    print("=" * 60)
    print("Example 3: File Encryption")
    print("=" * 60)
    
    # Create a test file
    test_file = "test_document.txt"
    encrypted_file = "test_document.txt.enc"
    decrypted_file = "test_document_decrypted.txt"
    
    password = "file_encryption_password"
    
    # Write test data
    test_content = "This is a test file.\n" * 1000
    with open(test_file, "w") as f:
        f.write(test_content)
    
    original_size = Path(test_file).stat().st_size
    print(f"Original file: {test_file} ({original_size:,} bytes)")
    
    # Encrypt
    print("Encrypting...")
    irene_cipher.encrypt_file(test_file, encrypted_file, password)
    encrypted_size = Path(encrypted_file).stat().st_size
    print(f"Encrypted file: {encrypted_file} ({encrypted_size:,} bytes)")
    
    # Decrypt
    print("Decrypting...")
    irene_cipher.decrypt_file(encrypted_file, decrypted_file, password)
    decrypted_size = Path(decrypted_file).stat().st_size
    print(f"Decrypted file: {decrypted_file} ({decrypted_size:,} bytes)")
    
    # Verify
    with open(test_file, "r") as f:
        original = f.read()
    with open(decrypted_file, "r") as f:
        decrypted = f.read()
    
    assert original == decrypted
    print("✓ File encryption/decryption successful!")
    
    # Cleanup
    os.remove(test_file)
    os.remove(encrypted_file)
    os.remove(decrypted_file)
    print("✓ Cleanup complete\n")


def example_key_generation():
    """Example: Generating secure random keys"""
    print("=" * 60)
    print("Example 4: Key Generation")
    print("=" * 60)
    
    # Generate multiple keys
    key1 = irene_cipher.generate_key()
    key2 = irene_cipher.generate_key()
    key3 = irene_cipher.generate_key()
    
    print(f"Key 1: {key1.hex()}")
    print(f"Key 2: {key2.hex()}")
    print(f"Key 3: {key3.hex()}")
    
    # Verify uniqueness
    assert len(key1) == 32
    assert len(key2) == 32
    assert len(key3) == 32
    assert key1 != key2 != key3
    
    print("\n✓ All keys are 32 bytes")
    print("✓ All keys are unique (random)\n")


def example_error_handling():
    """Example: Proper error handling"""
    print("=" * 60)
    print("Example 5: Error Handling")
    print("=" * 60)
    
    password = "correct_password"
    plaintext = "Secret message"
    
    # Encrypt with correct password
    ciphertext = irene_cipher.encrypt_text(plaintext, password)
    print("Encrypted with correct password")
    
    # Try to decrypt with wrong password
    print("\nAttempting to decrypt with wrong password...")
    try:
        irene_cipher.decrypt_text(ciphertext, "wrong_password")
        print("❌ Should have raised an exception!")
    except ValueError as e:
        print(f"✓ Caught expected error: {e}")
    
    # Try to decrypt tampered data
    print("\nAttempting to decrypt tampered ciphertext...")
    tampered = bytearray(ciphertext)
    tampered[-1] ^= 0xFF  # Flip bits in last byte
    
    try:
        irene_cipher.decrypt_text(bytes(tampered), password)
        print("❌ Should have raised an exception!")
    except ValueError as e:
        print(f"✓ Caught expected error: {e}")
    
    # Decrypt with correct password
    print("\nDecrypting with correct password...")
    decrypted = irene_cipher.decrypt_text(ciphertext, password)
    print(f"✓ Successfully decrypted: {decrypted}\n")


def example_large_file():
    """Example: Encrypting a larger file (demonstrates streaming)"""
    print("=" * 60)
    print("Example 6: Large File Encryption (10 MB)")
    print("=" * 60)
    
    large_file = "large_test.bin"
    encrypted_file = "large_test.bin.enc"
    decrypted_file = "large_test_decrypted.bin"
    
    password = "large_file_password"
    file_size = 10 * 1024 * 1024  # 10 MB
    
    # Create large file
    print(f"Creating {file_size:,} byte test file...")
    with open(large_file, "wb") as f:
        # Write in chunks to avoid memory issues
        chunk = b"X" * (1024 * 1024)  # 1 MB chunks
        for _ in range(10):
            f.write(chunk)
    
    original_size = Path(large_file).stat().st_size
    print(f"✓ Created: {original_size:,} bytes")
    
    # Encrypt
    print("Encrypting (streaming, low memory usage)...")
    irene_cipher.encrypt_file(large_file, encrypted_file, password)
    encrypted_size = Path(encrypted_file).stat().st_size
    print(f"✓ Encrypted: {encrypted_size:,} bytes")
    
    # Decrypt
    print("Decrypting (streaming, low memory usage)...")
    irene_cipher.decrypt_file(encrypted_file, decrypted_file, password)
    decrypted_size = Path(decrypted_file).stat().st_size
    print(f"✓ Decrypted: {decrypted_size:,} bytes")
    
    # Verify sizes match
    assert original_size == decrypted_size
    print("✓ File sizes match")
    
    # Cleanup
    os.remove(large_file)
    os.remove(encrypted_file)
    os.remove(decrypted_file)
    print("✓ Cleanup complete\n")


def example_multiple_encryptions():
    """Example: Same plaintext produces different ciphertexts"""
    print("=" * 60)
    print("Example 7: Nonce Uniqueness")
    print("=" * 60)
    
    password = "same_password"
    plaintext = "Same message every time"
    
    # Encrypt same message multiple times
    ct1 = irene_cipher.encrypt_text(plaintext, password)
    ct2 = irene_cipher.encrypt_text(plaintext, password)
    ct3 = irene_cipher.encrypt_text(plaintext, password)
    
    print(f"Plaintext: {plaintext}")
    print(f"Password: {password}")
    print(f"\nCiphertext 1: {ct1.hex()[:64]}...")
    print(f"Ciphertext 2: {ct2.hex()[:64]}...")
    print(f"Ciphertext 3: {ct3.hex()[:64]}...")
    
    # All should be different (due to random salt and nonce)
    assert ct1 != ct2
    assert ct2 != ct3
    assert ct1 != ct3
    print("\n✓ All ciphertexts are unique (random nonces)")
    
    # But all decrypt to same plaintext
    assert irene_cipher.decrypt_text(ct1, password) == plaintext
    assert irene_cipher.decrypt_text(ct2, password) == plaintext
    assert irene_cipher.decrypt_text(ct3, password) == plaintext
    print("✓ All decrypt to original plaintext\n")


def main():
    """Run all examples"""
    print("\n")
    print("╔" + "═" * 58 + "╗")
    print("║" + " " * 12 + "IRENE CIPHER - PYTHON EXAMPLES" + " " * 16 + "║")
    print("╚" + "═" * 58 + "╝")
    print()
    
    try:
        example_text_encryption()
        example_binary_encryption()
        example_file_encryption()
        example_key_generation()
        example_error_handling()
        example_large_file()
        example_multiple_encryptions()
        
        print("=" * 60)
        print("✓ ALL EXAMPLES COMPLETED SUCCESSFULLY!")
        print("=" * 60)
        print()
        
    except Exception as e:
        print(f"\n❌ Error: {e}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    main()
