#!/usr/bin/env python3
"""Agent for implementing end-to-end encryption (E2EE) for messaging using X25519 + AES-GCM."""

import json
import argparse
import os

try:
    from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey
    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
    from cryptography.hazmat.primitives.kdf.hkdf import HKDF
    from cryptography.hazmat.primitives import hashes, serialization
    HAS_CRYPTO = True
except ImportError:
    HAS_CRYPTO = False

NONCE_SIZE = 12
KEY_SIZE = 32
HKDF_INFO = b"e2ee-messaging-v1"


def generate_keypair():
    """Generate X25519 key pair for Diffie-Hellman key exchange."""
    private_key = X25519PrivateKey.generate()
    public_key = private_key.public_key()
    priv_bytes = private_key.private_bytes(
        serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption()
    )
    pub_bytes = public_key.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw)
    return {
        "private_key_hex": priv_bytes.hex(),
        "public_key_hex": pub_bytes.hex(),
        "algorithm": "X25519",
    }


def derive_shared_secret(my_private_hex, their_public_hex):
    """Derive shared secret using X25519 ECDH + HKDF-SHA256."""
    my_private = X25519PrivateKey.from_private_bytes(bytes.fromhex(my_private_hex))
    their_public = X25519PublicKey.from_public_bytes(bytes.fromhex(their_public_hex))
    shared_key = my_private.exchange(their_public)
    derived_key = HKDF(
        algorithm=hashes.SHA256(), length=KEY_SIZE, salt=None, info=HKDF_INFO
    ).derive(shared_key)
    return derived_key


def encrypt_message(message, shared_key_hex):
    """Encrypt a message using AES-256-GCM with a shared key."""
    key = bytes.fromhex(shared_key_hex)
    nonce = os.urandom(NONCE_SIZE)
    aesgcm = AESGCM(key)
    ciphertext = aesgcm.encrypt(nonce, message.encode("utf-8"), None)
    return {
        "nonce_hex": nonce.hex(),
        "ciphertext_hex": ciphertext.hex(),
        "algorithm": "AES-256-GCM",
    }


def decrypt_message(nonce_hex, ciphertext_hex, shared_key_hex):
    """Decrypt a message using AES-256-GCM."""
    key = bytes.fromhex(shared_key_hex)
    nonce = bytes.fromhex(nonce_hex)
    ciphertext = bytes.fromhex(ciphertext_hex)
    aesgcm = AESGCM(key)
    plaintext = aesgcm.decrypt(nonce, ciphertext, None)
    return {"plaintext": plaintext.decode("utf-8")}


def simulate_key_exchange(alice_name="Alice", bob_name="Bob"):
    """Simulate a complete key exchange between two parties."""
    alice_kp = generate_keypair()
    bob_kp = generate_keypair()

    alice_shared = derive_shared_secret(alice_kp["private_key_hex"], bob_kp["public_key_hex"])
    bob_shared = derive_shared_secret(bob_kp["private_key_hex"], alice_kp["public_key_hex"])

    keys_match = alice_shared == bob_shared
    return {
        "alice_public_key": alice_kp["public_key_hex"],
        "bob_public_key": bob_kp["public_key_hex"],
        "shared_secret_match": keys_match,
        "shared_key_hex": alice_shared.hex() if keys_match else None,
        "key_exchange": "X25519 ECDH",
        "kdf": "HKDF-SHA256",
        "encryption": "AES-256-GCM",
    }


def demo_full_flow():
    """Demonstrate complete E2EE message flow."""
    kx = simulate_key_exchange()
    if not kx["shared_secret_match"]:
        return {"error": "Key exchange failed"}
    shared_key = kx["shared_key_hex"]
    test_message = "Hello, this is an end-to-end encrypted message."
    encrypted = encrypt_message(test_message, shared_key)
    decrypted = decrypt_message(encrypted["nonce_hex"], encrypted["ciphertext_hex"], shared_key)
    return {
        "key_exchange": kx,
        "original_message": test_message,
        "encrypted": encrypted,
        "decrypted": decrypted,
        "integrity_check": decrypted["plaintext"] == test_message,
    }


def main():
    if not HAS_CRYPTO:
        print(json.dumps({"error": "cryptography library not installed"}))
        return
    parser = argparse.ArgumentParser(description="E2EE Messaging Agent (X25519 + AES-256-GCM)")
    sub = parser.add_subparsers(dest="command")
    sub.add_parser("keygen", help="Generate X25519 key pair")
    sub.add_parser("exchange", help="Simulate key exchange")
    sub.add_parser("demo", help="Full E2EE demo flow")
    e = sub.add_parser("encrypt", help="Encrypt message")
    e.add_argument("--message", required=True)
    e.add_argument("--key", required=True, help="Shared key hex")
    d = sub.add_parser("decrypt", help="Decrypt message")
    d.add_argument("--nonce", required=True)
    d.add_argument("--ciphertext", required=True)
    d.add_argument("--key", required=True, help="Shared key hex")
    args = parser.parse_args()
    if args.command == "keygen":
        result = generate_keypair()
    elif args.command == "exchange":
        result = simulate_key_exchange()
    elif args.command == "demo":
        result = demo_full_flow()
    elif args.command == "encrypt":
        result = encrypt_message(args.message, args.key)
    elif args.command == "decrypt":
        result = decrypt_message(args.nonce, args.ciphertext, args.key)
    else:
        parser.print_help()
        return
    print(json.dumps(result, indent=2, default=str))


if __name__ == "__main__":
    main()
