"""
Multi-Currency Wallet Manager
Handles multiple cryptocurrency wallets and transactions
"""
from .wallet_db import WalletDB
from .crypto_impl import CryptoFactory, CryptoTransaction
from .network_sync import NetworkSync
from typing import Dict, List, Optional
from decimal import Decimal
import asyncio
import json

class MultiCryptoWallet:
    def __init__(self):
        self.db = WalletDB()
        self.network_sync = NetworkSync(self.db)
        self.supported_currencies = ['BTC', 'ETH', 'SOL']
        
    async def initialize(self):
        """Initialize wallet system"""
        # Start network synchronization
        await self.network_sync.start()
        
    async def create_wallet(self, currency: str) -> Dict:
        """Create new wallet for specified currency"""
        if currency not in self.supported_currencies:
            raise ValueError(f"Unsupported currency: {currency}")
            
        # Get implementation for currency
        impl = CryptoFactory.get_implementation(currency)
        
        # Generate address
        address = impl.generate_address()
        
        # Save to database
        wallet_info = {
            'address': address,
            'currency': currency,
            'created_at': time.time()
        }
        self.db.save_wallet(wallet_info)
        
        return wallet_info
        
    async def get_balance(self, address: str, currency: str) -> Decimal:
        """Get wallet balance"""
        impl = CryptoFactory.get_implementation(currency)
        balance = await impl.get_balance(address)
        
        # Update balance in database
        self.db.update_balance(address, currency, balance)
        
        return balance
        
    async def send_transaction(self, 
                             from_address: str,
                             to_address: str,
                             amount: Decimal,
                             currency: str,
                             fee: Optional[Decimal] = None) -> CryptoTransaction:
        """Send cryptocurrency transaction"""
        impl = CryptoFactory.get_implementation(currency)
        
        # Create transaction
        tx_data = {
            'from': from_address,
            'to': to_address,
            'amount': str(amount),
            'fee': str(fee) if fee else None,
            'timestamp': time.time()
        }
        
        # Sign transaction
        signature = impl.sign_transaction(tx_data)
        tx_data['signature'] = signature.hex()
        
        # Broadcast to network
        tx_hash = await impl.broadcast_transaction(tx_data)
        
        # Create transaction record
        transaction = CryptoTransaction(
            tx_hash=tx_hash,
            from_address=from_address,
            to_address=to_address,
            amount=amount,
            currency=currency,
            fee=fee or Decimal('0'),
            status='pending',
            timestamp=time.time(),
            raw_tx=tx_data
        )
        
        # Save to database
        self.db.record_transaction(transaction.__dict__)
        
        return transaction
        
    async def get_transaction_history(self, address: str, currency: Optional[str] = None) -> List[CryptoTransaction]:
        """Get transaction history"""
        history = self.db.get_transaction_history(address)
        
        if currency:
            history = [tx for tx in history if tx['currency'] == currency]
            
        return [CryptoTransaction(**tx) for tx in history]
        
    async def get_prices(self) -> Dict[str, Decimal]:
        """Get current prices for all supported currencies"""
        return {
            currency: self.network_sync.get_price(currency)
            for currency in self.supported_currencies
        }
        
    def add_transaction_callback(self, currency: str, callback):
        """Add callback for transaction events"""
        self.network_sync.register_callback(currency, callback)
        
    async def stop(self):
        """Stop wallet system"""
        await self.network_sync.stop()
        self.db.close()
