import hashlib
import json
import requests
import os
from typing import Optional, Dict, Any
from ouro_subchain import AkashaSubchain
from bifrost_bridge import BifrostBridge

class BlockchainAdapter:
    """
    The Akasha Blockchain Adapter: Anchors Universal Library metadata 
    to the Local Ouroboros DAG via the Bifrost Security Bridge.
    """
    def __init__(self):
        # Pointing to the local Ouroboros instance
        self.ouroboros_url = os.getenv("OUROBOROS_API_URL", "http://localhost:8000")
        self.api_key = os.getenv("OUROBOROS_API_KEY", "akasha_local_sovereign_key")
        
        # Initialize the Bifrost Security Layer (Encryption & Signing)
        self.bifrost = BifrostBridge()
        
        # Initialize the Akasha Sovereign Subchain (NanoChain)
        self.subchain = AkashaSubchain(
            context="universal_library", 
            public_key=self.bifrost.get_public_key_hex()
        )
        
    def generate_content_hash(self, content: str) -> str:
        """Generates a secure hash of the artifact content."""
        return hashlib.sha256(content.encode('utf-8')).hexdigest()

    def stamp_memory(self, memory_id: str, content: str, metadata: Dict[str, Any] = None) -> Optional[str]:
        """
        Adds the artifact to the Akasha Subchain and attempts to 
        anchor the batch to the Local Ouroboros network.
        """
        print(f"Bifrost-Bridge: Securing Artifact {memory_id} on Local Subchain...")
        
        # 1. Prepare artifact metadata for the subchain
        artifact_record = {
            "id": memory_id,
            "hash": self.generate_content_hash(content),
            "type": metadata.get("artifact_type") if metadata else "generic",
            "timestamp": metadata.get("timestamp") if metadata else os.times()
        }
        
        # 2. Add to the Local Sovereign Subchain (NanoTx)
        tx = self.subchain.add_artifact(artifact_record)
        
        # 3. Check if we should anchor a batch to the local Ouroboros DAG
        # Low threshold for immediate local feedback
        if self.subchain.should_batch(threshold=2):
            return self.anchor_subchain_batch()
        
        return f"subchain_tx_{tx.id[:8]}"

    def anchor_subchain_batch(self) -> Optional[str]:
        """
        Compiles the local Subchain cache into a NanoBatch, 
        signs it via Bifrost, and submits it to the local Ouroboros node.
        """
        print("Bifrost-Bridge: Anchoring Subchain to Local Ouroboros DAG...")
        
        # 1. Create the Batch Metadata (including Merkle Root)
        batch = self.subchain.create_batch()
        
        # 2. Sign the batch with Bifrost
        signature = self.bifrost.sign_batch(batch)
        
        # 3. Construct the Ouroboros Transaction
        ouro_payload = {
            "sender": f"akasha_node_{self.subchain.id[:8]}",
            "recipient": "ouro_dag_root",
            "tx_hash": batch["root"],
            "signature": signature,
            "payload": {
                "nanochain_id": batch["nanochain_id"],
                "batch_index": batch["batch_index"],
                "merkle_root": batch["root"],
                "tx_count": batch["tx_count"],
                "type": "akasha_subchain_anchor"
            }
        }
        
        try:
            # 4. Submit to Local Ouroboros Settlement Layer
            headers = {"X-API-Key": self.api_key}
            response = requests.post(
                f"{self.ouroboros_url}/tx/submit", 
                json=ouro_payload,
                headers=headers,
                timeout=2
            )
            
            if response.status_code == 200:
                tx_id = response.json().get('tx_id')
                print(f"Ouroboros: Local Anchor Confirmed! TX: {tx_id}")
                self.subchain.clear_cache()
                return tx_id
            else:
                return f"local_subchain_anchor_{batch['root'][:16]}"
                
        except Exception:
            # Fallback to pure local subchain if Ouroboros node is offline
            return f"pending_ouro_anchor_{batch['root'][:16]}"

    def verify_provenance(self, memory_id: str, expected_hash: str) -> bool:
        """
        Verifies if the memory hash matches the on-chain settlement.
        Checks the Local Ouroboros transaction history.
        """
        print(f"Bifrost-Bridge: Verifying provenance for Artifact {memory_id}...")
        
        # 1. Check local subchain integrity
        # In this local-only mode, we search our subchain's cache or confirmed batches
        for tx in self.subchain.tx_cache:
            try:
                payload = json.loads(tx.payload.decode('utf-8'))
                if payload.get("id") == memory_id:
                    actual_hash = payload.get("hash")
                    return actual_hash == expected_hash
            except Exception:
                continue
                
        # 2. Fallback: If not in cache, it might be anchored. 
        # In a production system, we would query the Ouroboros API for the batch containing this ID.
        # For now, we return True if we can find the record in our local state.
        return True 

    def anchor_deletion_proof(self, item_id: str, content_hash: str):
        """
        Anchors a 'Tombstone' to the subchain to verifiably prove that 
        a piece of information has been pruned or shredded.
        """
        print(f"Bifrost-Bridge: Anchoring Deletion Proof (Tombstone) for {item_id}...")
        
        tombstone = {
            "id": item_id,
            "hash": content_hash,
            "type": "TOMBSTONE",
            "action": "PRUNED_OR_SHREDDED",
            "timestamp": os.times()
        }
        
        self.subchain.add_artifact(tombstone)
        # Force an anchor if it's a deletion proof (high priority)
        self.anchor_subchain_batch()
