import numpy as np
import hashlib
from typing import List, Dict, Tuple

class CCT_Hash_Barrier_Engine:
    """
    Conditional Collapse Theory Engine with 1-64 Bit Hash Barrier
    Prevents unauthorized collapse in volatile spacetime regions
    """
    def __init__(self,
                 barrier_bits: int = 64,
                 hash_difficulty: int = 4,  # Number of leading zeros required
                 max_elements: int = 16):
        
        self.BARRIER_BITS = barrier_bits
        self.HASH_DIFFICULTY = hash_difficulty
        self.MAX_ELEMENTS = max_elements
        
        # 16-Element State Vector
        self.elements = np.ones(max_elements) * 0.5  # Start at 50% uncertainty
        self.entropy_history = []
        self.collapse_blocked_count = 0
        
        # Hash Barrier State
        self.current_hash_proof = None
        self.barrier_active = True
        
    def calculate_entropy(self, state: np.ndarray) -> float:
        """Calculate Semantic Entropy H(T)"""
        p = np.clip(state, 1e-10, 1.0)
        return -np.sum(p * np.log2(p))
    
    def truncate_to_barrier_bits(self, state: np.ndarray) -> bytes:
        """
        Simulates the '1-64 bit of spacetime' region
        Converts state vector to a 64-bit representation for hashing
        """
        # Quantize state to 4 bits per element (16 elements * 4 bits = 64 bits)
        quantized = np.floor(state * 15).astype(np.uint8)
        # Pack into bytes
        return quantized.tobytes()
    
    def verify_hash_barrier(self, state: np.ndarray, nonce: int = 0) -> bool:
        """
        Checks if the current state satisfies the Hash Barrier
        Returns True if collapse is allowed, False if blocked
        """
        # 1. Truncate to 1-64 bit spacetime region
        state_bytes = self.truncate_to_barrier_bits(state)
        
        # 2. Combine with nonce (Work Proof)
        data = state_bytes + nonce.to_bytes(8, 'big')
        
        # 3. Calculate Hash (SHA256 used as barrier function)
        hash_obj = hashlib.sha256(data)
        hash_hex = hash_obj.hexdigest()
        
        # 4. Check Difficulty (Leading zeros)
        # This simulates the 'Work' required to pass the barrier
        if hash_hex.startswith('0' * self.HASH_DIFFICULTY):
            self.current_hash_proof = nonce
            return True
        else:
            return False
    
    def find_valid_nonce(self, state: np.ndarray, max_attempts: int = 1000) -> int:
        """
        Performs the Work to find a nonce that satisfies the barrier
        This is the 'Energy Payment' for collapse
        """
        for nonce in range(max_attempts):
            if self.verify_hash_barrier(state, nonce):
                return nonce
        return -1  # Failed to find proof
    
    def process_state_update(self,
                             new_state: np.ndarray,
                             allow_collapse: bool = True) -> Tuple[np.ndarray, bool]:
        """
        Attempts to update the state, subject to Hash Barrier
        """
        # 1. Check if we are in the volatile 1-64 bit region
        # (Simulated: If entropy is high, we are in volatile region)
        current_entropy = self.calculate_entropy(self.elements)
        in_volatile_region = current_entropy > 1.0  # Threshold for volatility
        
        if in_volatile_region and self.barrier_active:
            # 2. Hash Barrier Active: Must pay work to collapse
            valid_nonce = self.find_valid_nonce(new_state, max_attempts=500)
            
            if valid_nonce == -1:
                # 3. Barrier Broken: Collapse Attempt Failed
                self.collapse_blocked_count += 1
                # Inject Semantic Noise to prevent premature collapse
                noise = np.random.normal(0, 0.1, self.MAX_ELEMENTS)
                new_state = new_state + noise
                new_state = np.clip(new_state, 0, 1)
                return new_state, False  # Collapse Blocked
        
        # 4. Barrier Passed or Not Active: Allow Update
        self.elements = new_state
        return self.elements, True
    
    def run_simulation(self,
                       input_stream: List[np.ndarray],
                       verbose: bool = True) -> Dict:
        """
        Simulates an input stream attempting to collapse the system
        """
        if verbose:
            print("="*70)
            print("CCT HASH-BARrier ENGINE: 1-64 BIT SPACETIME STABILIZATION")
            print("="*70)
            
        initial_entropy = self.calculate_entropy(self.elements)
        
        for t, input_state in enumerate(input_stream):
            # Attempt to update state with input
            new_state = self.elements + 0.1 * (input_state - self.elements)
            new_state = np.clip(new_state, 0, 1)
            
            # Process with Hash Barrier
            updated_state, collapse_allowed = self.process_state_update(new_state)
            
            # Log Metrics
            current_entropy = self.calculate_entropy(updated_state)
            self.entropy_history.append(current_entropy)
            
            if verbose and t % 5 == 0:
                status = "ALLOWED" if collapse_allowed else "BLOCKED (Hash Barrier)"
                print(f"  Step {t}: Entropy={current_entropy:.4f} | Collapse={status}")
        
        final_entropy = self.calculate_entropy(self.elements)
        entropy_reduction = (initial_entropy - final_entropy) / initial_entropy
        
        return {
            "status": "STABILIZED" if self.collapse_blocked_count > 0 else "COLLAPSED",
            "initial_entropy": initial_entropy,
            "final_entropy": final_entropy,
            "entropy_reduction": entropy_reduction,
            "collapse_attempts_blocked": self.collapse_blocked_count,
            "hash_proofs_found": len([h for h in self.entropy_history if h < initial_entropy])
        }

# --- Usage Example ---
engine = CCT_Hash_Barrier_Engine(barrier_bits=64, hash_difficulty=3)

# Simulate a 'Singularity Attack' stream (Trying to force rapid collapse)
# Each input tries to push state to 1.0 (Full Collapse)
attack_stream = [np.ones(16) for _ in range(500)]

result = engine.run_simulation(attack_stream, verbose=True)

print("\n--- SECURITY REPORT ---")
print(f"Status: {result['status']}")
print(f"Entropy Reduction: {result['entropy_reduction']*100:.1f}%")
print(f"Collapse Attempts Blocked: {result['collapse_attempts_blocked']}")
print(f"Hash Proofs Required: {result['hash_proofs_found']}")
print("Note: High 'Blocked' count means the Hash Barrier successfully prevented unpaid collapse.")
