"""
Real Bitcoin network communication
"""
import socket
import struct
import hashlib
import time
from typing import Optional, Dict, Any

class BitcoinNetwork:
    def __init__(self, network='bitcoin'):
        self.network = network
        self.magic = 0xD9B4BEF9 if network == 'bitcoin' else 0xDAB5BFFA
        self.version = 70015
        self.services = 0
        self.peers = []
        
    def connect(self, seed_node: str = 'seed.bitcoin.sipa.be', port: int = 8333):
        """
        Connect to Bitcoin network
        """
        try:
            # Resolve DNS seed
            addresses = socket.getaddrinfo(seed_node, port, proto=socket.IPPROTO_TCP)
            
            for addr in addresses:
                try:
                    # Create socket
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.settimeout(10)
                    
                    # Connect
                    sock.connect((addr[4][0], port))
                    
                    # Send version message
                    if self._send_version(sock):
                        self.peers.append({
                            'socket': sock,
                            'address': addr[4][0],
                            'port': port
                        })
                        return True
                except Exception as e:
                    print(f"Failed to connect to {addr[4][0]}: {str(e)}")
                    continue
                    
            return False
            
        except Exception as e:
            raise Exception(f"Network connection failed: {str(e)}")
            
    def _send_version(self, sock: socket.socket) -> bool:
        """
        Send version message to peer
        """
        try:
            # Build version message
            version = struct.pack('<I', self.version)
            services = struct.pack('<Q', self.services)
            timestamp = struct.pack('<Q', int(time.time()))
            
            # Add addr_recv and addr_from
            addr_recv = struct.pack('<Q', 0) + bytes([0]*16) + bytes([0]*2)
            addr_from = struct.pack('<Q', 0) + bytes([0]*16) + bytes([0]*2)
            
            # Add nonce
            nonce = struct.pack('<Q', int.from_bytes(os.urandom(8), 'little'))
            
            # User agent (empty)
            user_agent = bytes([0])
            
            # Start height (0)
            start_height = struct.pack('<I', 0)
            
            # Relay flag
            relay = bytes([0])
            
            # Combine message
            payload = version + services + timestamp + addr_recv + addr_from + nonce + user_agent + start_height + relay
            
            # Add header
            message = self._create_message('version', payload)
            
            # Send message
            sock.send(message)
            
            # Wait for verack
            response = sock.recv(1024)
            if b'verack' in response:
                return True
                
            return False
            
        except Exception as e:
            print(f"Version handshake failed: {str(e)}")
            return False
            
    def _create_message(self, command: str, payload: bytes) -> bytes:
        """Create Bitcoin protocol message"""
        # Add magic bytes
        message = struct.pack('<I', self.magic)
        
        # Add command (12 bytes, padded with nulls)
        message += command.encode('ascii')[:12].ljust(12, b'\x00')
        
        # Add payload length
        message += struct.pack('<I', len(payload))
        
        # Add checksum (first 4 bytes of double SHA256 of payload)
        checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4]
        message += checksum
        
        # Add payload
        message += payload
        
        return message
        
    def broadcast_transaction(self, transaction: bytes) -> bool:
        """
        Broadcast transaction to network
        """
        success = False
        for peer in self.peers:
            try:
                message = self._create_message('tx', transaction)
                peer['socket'].send(message)
                success = True
            except Exception as e:
                print(f"Failed to broadcast to {peer['address']}: {str(e)}")
                continue
        return success
