"""
Integrates the mining system with Bitcoin mainnet
"""
from typing import Dict, Any, Optional
import time
import requests
import hashlib
import json

class NetworkIntegration:
    def __init__(self, wallet_address: str = None):
        self.api_base = "https://api.bitaps.com/btc/v1"
        self.node = "seed.bitcoin.sipa.be"  # Bitcoin mainnet seed node
        # Use the provided wallet address or load from my_wallet.json
        if wallet_address:
            self.wallet_address = wallet_address
        else:
            try:
                with open('my_wallet.json', 'r') as f:
                    wallet_data = json.load(f)
                self.wallet_address = wallet_data['address']
                print(f"Using wallet address: {self.wallet_address}")
            except Exception as e:
                print(f"Error loading wallet: {e}")
                self.wallet_address = "1Ks4WtCEK96BaBF7HSuCGt3rEpVKPqcJKf"  # Your default address
        self.last_template = None
        self.last_template_time = 0
        
    def connect(self) -> bool:
        """Connect to Bitcoin mainnet"""
        try:
            # Test connection by getting latest block
            response = requests.get(f"{self.api_base}/blockchain/blocks/last")
            return response.status_code == 200
        except Exception as e:
            print(f"Failed to connect to testnet: {e}")
            return False
        
    def get_block_template(self) -> Dict[str, Any]:
        """Get current block template from testnet"""
        try:
            # Only get new template every 30 seconds
            current_time = time.time()
            if self.last_template and current_time - self.last_template_time < 30:
                return self.last_template
            
            # Get real mining template from network
            getwork_url = "https://btc.getwork.org/getwork"
            headers = {'User-Agent': 'BTC-Miner/1.0'}
            response = requests.post(getwork_url, headers=headers)
            
            if response.status_code != 200:
                raise Exception("Failed to get work from network")
                
            work = response.json()
            current_block = work['result']
            
            # Get current network difficulty
            diff_url = "https://blockchain.info/q/getdifficulty"
            diff_response = requests.get(diff_url)
            if diff_response.status_code != 200:
                raise Exception("Failed to get network difficulty")
                
            network_difficulty = float(diff_response.text)
            
            # Calculate proper target from real network difficulty
            exp = int(network_difficulty).bit_length()
            target = int((0xffff * 2**(8*(0x1d - 3))) / network_difficulty)
            
            print(f"Mining at difficulty: {network_difficulty}")
            print(f"Network target: {hex(target)}")
            
            # Construct template with real network data
            template = {
                'version': current_block['version'],
                'previous_block': current_block['previousblockhash'],
                'merkle_root': current_block['merkleroot'],
                'timestamp': int(time.time()),
                'bits': current_block['bits'],
                'height': current_block['height'],
                'target': target,
                'network_difficulty': network_difficulty
            }
            
            self.last_template = template
            self.last_template_time = current_time
            
            return template
            
        except Exception as e:
            print(f"Error getting block template: {str(e)}")
            # Return last known good template or test values
            return self.last_template or {
                'version': 0x20000000,
                'previous_block': '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f',
                'merkle_root': '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b',
                'timestamp': int(time.time()),
                'bits': 0x1f00ffff,  # Easier difficulty for testing
                'target': 0x00000000ffff0000000000000000000000000000000000000000000000000000 * 16,  # 16x easier
                'height': 800000,
                'network_difficulty': None
            }
        
    def submit_block(self, block_header: bytes, nonce: int) -> bool:
        """Submit found block to testnet"""
        try:
            # Convert block to hex
            block_hex = block_header.hex()
            
            # Calculate block hash
            block_hash = hashlib.sha256(hashlib.sha256(block_header).digest()).digest()
            
            # Submit block to mainnet nodes
            submit_url = f"https://api.smartbit.com.au/v1/blockchain/pushtx"
            response = requests.post(submit_url, json={
                'hex': block_hex
            })
            
            if response.status_code == 200:
                print(f"Block successfully submitted to mainnet!")
                print(f"Block hash: {block_hash.hex()}")
                
                # Save reward data
                current_time = int(time.time())
                reward_data = {
                    'block_hash': block_hash.hex(),
                    'nonce': nonce,
                    'timestamp': current_time,
                    'reward': 6.25,  # Current block reward in BTC
                    'wallet_address': self.wallet_address
                }
                
                try:
                    with open('pending_rewards.json', 'r') as f:
                        rewards = json.load(f)
                except:
                    rewards = []
                    
                rewards.append(reward_data)
                
                with open('pending_rewards.json', 'w') as f:
                    json.dump(rewards, f, indent=2)
                    
                # Update wallet mining stats
                try:
                    with open('my_wallet.json', 'r') as f:
                        wallet_data = json.load(f)
                    
                    wallet_data['total_mined'] += 6.25
                    wallet_data['mining_stats']['total_blocks_mined'] += 1
                    wallet_data['mining_stats']['last_reward'] = current_time
                    wallet_data['metadata']['last_updated'] = current_time
                    
                    with open('my_wallet.json', 'w') as f:
                        json.dump(wallet_data, f, indent=2)
                except Exception as e:
                    print(f"Error updating wallet stats: {e}")
                    
                return True
                
            print(f"Block submission failed: {response.text}")
            return False
            
        except Exception as e:
            print(f"Error submitting block: {str(e)}")
            return False
            
    def _bits_to_target(self, bits: str) -> int:
        """Convert compact bits to target"""
        bits = int(bits, 16)
        shift = (bits >> 24) & 0xff
        target = (bits & 0x00ffffff) * (2 ** (8 * (shift - 3)))
        return target