#!/usr/bin/env python3
# Copyright (c) Subzero Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

"""
Airdrop operations example demonstrating requesting test tokens
"""

import time
from rialo_py_cdk import (
    generate_keypair,
    get_localnet_url,
    Wallet,
    HttpRpcClient,
    airdrop_rlo,
    rlo_to_kelvin,
    kelvin_to_rlo,
)


def airdrop_operations_example():
    """Run airdrop operations example demonstrating requesting test tokens."""
    print('🪂 Starting Rialo CDK Airdrop Operations Example\n')

    try:
        # 1. Create a wallet for receiving the airdrop
        print('1. Creating wallet for airdrop...')
        keypair = generate_keypair()
        wallet = Wallet('airdrop-wallet', keypair)
        wallet_pubkey = wallet.get_public_key()
        print(f'   Wallet address: {wallet.get_public_key_string()}')

        # 2. Create RPC client (using localhost for airdrops)
        print('2. Creating RPC client...')
        client = HttpRpcClient(get_localnet_url())
        print(f'   Created RPC client for local network: {get_localnet_url()}')

        # 3. Check initial balance
        print('3. Checking initial balance...')
        try:
            initial_balance = client.get_balance(wallet_pubkey)
            print(f'   Initial balance: {initial_balance} kelvin')
            initial_rlo = kelvin_to_rlo(initial_balance)
            print(f'   Initial balance: {initial_rlo:.6f} RLO')
        except Exception as error:
            print('   Initial balance: 0 kelvin (account does not exist yet)')
            initial_balance = 0
            initial_rlo = 0.0

        # 4. Request airdrop using convenience function
        print('4. Requesting airdrop using convenience function...')
        airdrop_amount_rlo = 1.0  # 1 RLO
        try:
            airdrop_signature = airdrop_rlo(client, wallet_pubkey, airdrop_amount_rlo)
            print(f'   ✅ Airdrop requested successfully!')
            print(f'   Transaction signature: {airdrop_signature}')
            print(f'   Amount requested: {airdrop_amount_rlo} RLO')
            
            # 5. Wait a moment for the transaction to process
            print('5. Waiting for transaction confirmation...')
            time.sleep(5)  # Wait 5 seconds
            
            # 6. Check balance after airdrop
            print('6. Checking balance after airdrop...')
            try:
                new_balance = client.get_balance(wallet_pubkey)
                new_balance_rlo = kelvin_to_rlo(new_balance)
                print(f'   New balance: {new_balance} kelvin')
                print(f'   New balance: {new_balance_rlo:.6f} RLO')
                
                balance_increase = new_balance - initial_balance
                balance_increase_rlo = kelvin_to_rlo(balance_increase)
                print(f'   Balance increase: {balance_increase} kelvin')
                print(f'   Balance increase: {balance_increase_rlo:.6f} RLO')
                print(f'   Airdrop successful: {"✅" if new_balance > initial_balance else "❌"}')
            except Exception as error:
                print('   ⏳ Balance check failed, transaction might still be processing')
                print(f'   Error: {error}')
            
        except Exception as error:
            print(f'   ❌ Airdrop request failed: {error}')
            print('   This could happen if:')
            print('   - The local Rialo node is not running')
            print('   - Airdrop limits have been reached')
            print('   - Network connectivity issues')
            print('   - The node is not configured for airdrops')

        # 7. Request smaller airdrop directly using RPC client
        print('7. Trying direct RPC airdrop request...')
        smaller_amount_kelvin = rlo_to_kelvin(0.1)  # 0.1 RLO
        try:
            small_airdrop_sig = client.request_airdrop(wallet_pubkey, smaller_amount_kelvin)
            print(f'   ✅ Smaller airdrop requested successfully!')
            print(f'   Transaction signature: {small_airdrop_sig}')
            print(f'   Amount requested: {smaller_amount_kelvin} kelvin (0.1 RLO)')
            
            # Wait and check balance
            print('   ⏳ Waiting for confirmation...')
            time.sleep(3)
            
            try:
                updated_balance = client.get_balance(wallet_pubkey)
                updated_balance_rlo = kelvin_to_rlo(updated_balance)
                print(f'   Updated balance: {updated_balance} kelvin ({updated_balance_rlo:.6f} RLO)')
            except Exception as error:
                print(f'   Could not check updated balance: {error}')
                
        except Exception as error:
            print(f'   ❌ Smaller airdrop also failed: {error}')

        # 8. Demonstrate unit conversions
        print('8. Demonstrating unit conversions...')
        test_amounts_rlo = [0.1, 0.5, 1.0, 2.5, 10.0]
        print('   RLO to Kelvin conversions:')
        for rlo_amount in test_amounts_rlo:
            kelvin_amount = rlo_to_kelvin(rlo_amount)
            back_to_rlo = kelvin_to_rlo(kelvin_amount)
            print(f'     {rlo_amount} RLO = {kelvin_amount} kelvin = {back_to_rlo} RLO')

        # 9. Show useful information
        print('9. Airdrop information and tips...')
        print('   💡 Tips for successful airdrops:')
        print('   - Make sure your local Rialo node is running')
        print('   - Node should be started with airdrop functionality enabled')
        print('   - Airdrop amounts are typically limited per request')
        print('   - Multiple requests may be needed for larger amounts')
        print('   - Wait between requests to avoid rate limiting')
        print(f'   - Your wallet address: {wallet.get_public_key_string()}')
        print(f'   - Local node endpoint: {get_localnet_url()}')

        # 10. Test multiple small airdrops
        print('10. Testing multiple small airdrops...')
        small_amounts = [0.01, 0.02, 0.05]  # Small amounts in RLO
        for amount in small_amounts:
            try:
                print(f'    Requesting {amount} RLO airdrop...')
                signature = airdrop_rlo(client, wallet_pubkey, amount)
                print(f'    ✅ Success: {signature}')
                time.sleep(1)  # Small delay between requests
            except Exception as error:
                print(f'    ❌ Failed: {error}')

        # 11. Final balance check
        print('11. Final balance check...')
        try:
            final_balance = client.get_balance(wallet_pubkey)
            final_balance_rlo = kelvin_to_rlo(final_balance)
            total_received = final_balance - initial_balance
            total_received_rlo = kelvin_to_rlo(total_received)
            
            print(f'    Final balance: {final_balance} kelvin ({final_balance_rlo:.6f} RLO)')
            print(f'    Total received: {total_received} kelvin ({total_received_rlo:.6f} RLO)')
            
        except Exception as error:
            print(f'    Could not check final balance: {error}')

        # 12. Example summary
        print('12. Example summary...')
        print('    📚 This example demonstrates:')
        print('    - Creating a wallet for receiving airdrops')
        print('    - Setting up an RPC client connection')
        print('    - Checking account balances before/after operations')
        print('    - Requesting airdrops with proper amounts')
        print('    - Using both convenience functions and direct RPC calls')
        print('    - Handling network errors gracefully')
        print('    - Converting between RLO and kelvin units')
        print('    - Multiple airdrop strategies and error handling')
        print('    ✨ The Python bindings work correctly even when network fails!')

        print('\n✅ Airdrop operations completed successfully!')

    except Exception as error:
        print(f'❌ Error during airdrop operations: {error}')
        raise error


def main():
    """Run the airdrop operations example."""
    try:
        airdrop_operations_example()
        print('🎉 Airdrop example finished!')
    except Exception as error:
        print(f'💥 Airdrop example failed: {error}')
        import traceback
        traceback.print_exc()
        exit(1)


if __name__ == "__main__":
    main()