"""
MessageEnvelope - Tamper-proof message container for multi-agent communication

Uses MarkBluHasher for quantum-resistant message signing and verification.
"""

import json
from datetime import datetime
from typing import Dict, Any, Optional
from qalron.layer1 import MarkBluHasher


class MessageEnvelope:
    """
    Cryptographically signed message container.
    
    Provides tamper detection for agent-to-agent communication using
    quantum-resistant MarkBluHasher signatures.
    
    Example:
        >>> hasher = MarkBluHasher()
        >>> envelope = MessageEnvelope("agent1", "agent2", "Transfer $1M")
        >>> envelope.sign(hasher)
        >>> envelope.verify(hasher)  # True
        >>> envelope.content = "Transfer $100K"  # Tamper!
        >>> envelope.verify(hasher)  # False - tamper detected!
    """
    
    def __init__(
        self,
        sender: str,
        receiver: str,
        content: str,
        metadata: Optional[Dict[str, Any]] = None
    ):
        """
        Create a new message envelope.
        
        Args:
            sender: Agent ID sending the message
            receiver: Agent ID receiving the message
            content: Message content (will be signed)
            metadata: Optional metadata (e.g., priority, tags)
        """
        self.sender = sender
        self.receiver = receiver
        self.content = content
        self.metadata = metadata or {}
        self.timestamp = datetime.utcnow().isoformat()
        self.signature = None  # Set by sign()
    
    def _create_payload(self) -> str:
        """
        Create canonical payload for signing.
        
        Returns deterministic string representation to ensure
        signature consistency.
        """
        payload = f"{self.sender}|{self.receiver}|{self.content}|{self.timestamp}"
        return payload
    
    def sign(self, hasher: MarkBluHasher) -> str:
        """
        Sign the message with MarkBluHasher.
        
        Creates quantum-resistant signature that can detect any tampering.
        
        Args:
            hasher: MarkBluHasher instance for signing
            
        Returns:
            Signature as hexadecimal string
        """
        payload = self._create_payload()
        self.signature = hasher.sign(payload)
        return self.signature
    
    def verify(self, hasher: MarkBluHasher) -> bool:
        """
        Verify message integrity using signature.
        
        Args:
            hasher: MarkBluHasher instance (must be same as used for signing)
            
        Returns:
            True if message is unmodified, False if tampered
        """
        if not self.signature:
            raise ValueError("Message not signed. Call sign() first.")
        
        payload = self._create_payload()
        return hasher.verify(payload, self.signature)
    
    def to_dict(self) -> Dict[str, Any]:
        """
        Convert envelope to dictionary for serialization.
        
        Returns:
            Dictionary representation of the envelope
        """
        return {
            "sender": self.sender,
            "receiver": self.receiver,
            "content": self.content,
            "metadata": self.metadata,
            "timestamp": self.timestamp,
            "signature": self.signature
        }
    
    def to_json(self) -> str:
        """
        Convert envelope to JSON string.
        
        Returns:
            JSON string representation
        """
        return json.dumps(self.to_dict(), indent=2)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'MessageEnvelope':
        """
        Create envelope from dictionary.
        
        Args:
            data: Dictionary with envelope fields
            
        Returns:
            MessageEnvelope instance
        """
        envelope = cls(
            sender=data["sender"],
            receiver=data["receiver"],
            content=data["content"],
            metadata=data.get("metadata", {})
        )
        envelope.timestamp = data.get("timestamp", envelope.timestamp)
        envelope.signature = data.get("signature")
        return envelope
    
    def __repr__(self) -> str:
        """String representation for debugging"""
        return f"MessageEnvelope(from={self.sender}, to={self.receiver}, signed={bool(self.signature)})"
