"""
Real Bitcoin block template generation
"""
from typing import Dict, Any
import struct
import time
import hashlib
from bitcoinlib.services.services import Service
from bitcoinlib.transactions import Transaction

class BlockTemplateGenerator:
    def __init__(self, network='bitcoin'):
        self.service = Service(network=network)
        self.version = 0x20000000  # Version 2 with BIP9 signaling
        
    def get_block_template(self) -> Dict[str, Any]:
        """
        Get real Bitcoin block template from network
        """
        try:
            # Get latest block info
            latest_block = self.service.getblock(self.service.getbestblockhash())
            
            # Get mempool transactions
            mempool_txs = self.service.getmempool()
            
            # Current timestamp
            timestamp = int(time.time())
            
            # Current difficulty target (needs proper calculation)
            bits = latest_block['bits']
            
            # Build template
            template = {
                'version': self.version,
                'previous_block': latest_block['hash'],
                'timestamp': timestamp,
                'bits': bits,
                'transactions': mempool_txs,
                'height': latest_block['height'] + 1,
                'coinbase_value': self._calculate_reward(latest_block['height'] + 1)
            }
            
            # Add merkle root after transaction selection
            template['merkle_root'] = self._calculate_merkle_root(template['transactions'])
            
            return template
            
        except Exception as e:
            raise Exception(f"Failed to get block template: {str(e)}")
            
    def _calculate_reward(self, height: int) -> int:
        """Calculate correct block reward based on current height"""
        halvings = height // 210000
        if halvings >= 64:  # Max halvings
            return 0
            
        reward = 50 * 100000000  # Initial reward in satoshis
        reward >>= halvings  # Divide by 2 for each halving
        return reward
        
    def _calculate_merkle_root(self, transactions: list) -> str:
        """Calculate real merkle root from transaction list"""
        if not transactions:
            return hashlib.sha256(hashlib.sha256(b'').digest()).digest()
            
        # Convert transactions to hash list
        tx_hashes = [tx['hash'] for tx in transactions]
        
        while len(tx_hashes) > 1:
            if len(tx_hashes) % 2 == 1:
                tx_hashes.append(tx_hashes[-1])
                
            next_level = []
            for i in range(0, len(tx_hashes), 2):
                combined = tx_hashes[i] + tx_hashes[i+1]
                next_level.append(hashlib.sha256(hashlib.sha256(combined).digest()).digest())
            tx_hashes = next_level
            
        return tx_hashes[0].hex()
