# frozen_string_literal: true

#
# Synor IBC SDK Examples for Ruby
#
# Demonstrates Inter-Blockchain Communication operations:
# - Chain and channel management
# - Cross-chain token transfers
# - Packet lifecycle handling
# - Relayer operations
# - Connection monitoring
#

require 'synor/ibc'

class IbcExample
  def initialize(ibc)
    @ibc = ibc
  end

  def run_chains_example
    puts '=== Chain Information ==='

    # List connected chains
    chains = @ibc.chains.list
    puts "Connected chains: #{chains.length}"
    chains.first(5).each do |chain|
      puts "  #{chain.chain_id}: #{chain.name} (#{chain.status})"
    end

    # Get specific chain info
    cosmos_hub = @ibc.chains.get('cosmoshub-4')
    puts "\n#{cosmos_hub.name}:"
    puts "  Chain ID: #{cosmos_hub.chain_id}"
    puts "  RPC endpoint: #{cosmos_hub.rpc_endpoint}"
    puts "  Block height: #{cosmos_hub.latest_height}"
    puts "  Active channels: #{cosmos_hub.active_channels}"

    # Get chain clients
    clients = @ibc.chains.get_clients('cosmoshub-4')
    puts "\nIBC clients: #{clients.length}"
    clients.first(3).each do |client|
      puts "  #{client.client_id}: #{client.chain_id} (#{client.client_type})"
    end
    puts
  end

  def run_channels_example
    puts '=== Channel Management ==='

    # List channels
    channels = @ibc.channels.list
    puts "IBC channels: #{channels.length}"
    channels.first(5).each do |channel|
      puts "  #{channel.channel_id}: #{channel.source_chain} <-> #{channel.dest_chain} (#{channel.state})"
    end

    # Get channel details
    channel_id = 'channel-0'
    channel = @ibc.channels.get(channel_id)
    puts "\nChannel #{channel_id}:"
    puts "  State: #{channel.state}"
    puts "  Port: #{channel.port_id}"
    puts "  Counterparty: #{channel.counterparty_channel_id}"
    puts "  Connection: #{channel.connection_id}"
    puts "  Ordering: #{channel.ordering}"
    puts "  Version: #{channel.version}"

    # Create a new channel (4-step handshake)
    puts "\nInitiating channel creation..."
    init_result = @ibc.channels.init(
      source_chain: 'synor-mainnet',
      dest_chain: 'osmosis-1',
      port_id: 'transfer',
      version: 'ics20-1'
    )
    puts "  ChanOpenInit sent: #{init_result.channel_id}"

    # In production, the following steps happen through relayers:
    # ChanOpenTry -> ChanOpenAck -> ChanOpenConfirm

    # Get channel statistics
    stats = @ibc.channels.get_stats(channel_id)
    puts "\nChannel statistics:"
    puts "  Packets sent: #{stats.packets_sent}"
    puts "  Packets received: #{stats.packets_received}"
    puts "  Packets acknowledged: #{stats.packets_acknowledged}"
    puts "  Packets timed out: #{stats.packets_timed_out}"
    puts
  end

  def run_transfer_example
    puts '=== Cross-Chain Transfers ==='

    # Get transfer routes
    puts 'Available transfer routes:'
    routes = @ibc.transfers.get_routes('ATOM', 'synor-mainnet')
    routes.each do |route|
      puts "  #{route.source_chain} -> #{route.dest_chain}: #{route.channel_id}"
      puts "    Estimated time: #{route.estimated_time}"
      puts "    Fee: #{route.fee} #{route.fee_asset}"
    end

    # Initiate a transfer
    puts "\nInitiating transfer..."
    transfer = @ibc.transfers.send(
      source_chain: 'cosmoshub-4',
      dest_chain: 'synor-mainnet',
      channel_id: 'channel-0',
      asset: 'uatom',
      amount: '1000000', # 1 ATOM
      sender: 'cosmos1abc...',
      receiver: 'synor1xyz...',
      timeout: 1800, # 30 minutes in seconds
      memo: 'IBC transfer test'
    )

    puts 'Transfer initiated:'
    puts "  Transfer ID: #{transfer.transfer_id}"
    puts "  Sequence: #{transfer.sequence}"
    puts "  Status: #{transfer.status}"

    # Track transfer status
    puts "\nTracking transfer..."
    status = @ibc.transfers.get_status(transfer.transfer_id)
    puts "  Current status: #{status.status}"
    puts "  Source tx: #{status.source_tx_hash}"
    puts "  Dest tx: #{status.dest_tx_hash}" if status.dest_tx_hash

    # Get transfer history
    history = @ibc.transfers.get_history(limit: 5)
    puts "\nRecent transfers: #{history.length}"
    history.each do |tx|
      puts "  #{tx.transfer_id}: #{tx.amount} #{tx.asset} (#{tx.status})"
    end
    puts
  end

  def run_packet_example
    puts '=== Packet Handling ==='

    # Get pending packets
    pending_packets = @ibc.packets.get_pending('channel-0')
    puts "Pending packets: #{pending_packets.length}"
    pending_packets.first(5).each do |packet|
      puts "  Seq #{packet.sequence}: #{packet.source_port} -> #{packet.dest_port}"
    end

    # Get packet details
    if pending_packets.any?
      packet = @ibc.packets.get('channel-0', pending_packets.first.sequence)
      puts "\nPacket #{packet.sequence}:"
      puts "  Source: #{packet.source_port}/#{packet.source_channel}"
      puts "  Dest: #{packet.dest_port}/#{packet.dest_channel}"
      puts "  Timeout height: #{packet.timeout_height}"
      puts "  Timeout timestamp: #{packet.timeout_timestamp}"
      data_hex = packet.data.unpack1('H*')
      puts "  Data: #{data_hex[0, 64]}..."
    end

    # Query packet commitments
    commitments = @ibc.packets.get_commitments('channel-0')
    puts "\nPacket commitments: #{commitments.length}"

    # Query unreceived packets
    unreceived = @ibc.packets.get_unreceived('channel-0', [1, 2, 3, 4, 5])
    puts "Unreceived packets: #{unreceived.join(', ')}"

    # Query acknowledgements
    acks = @ibc.packets.get_acknowledgements('channel-0')
    puts "Packet acknowledgements: #{acks.length}"
    puts
  end

  def run_relayer_example
    puts '=== Relayer Operations ==='

    # Get relayer status
    relayers = @ibc.relayer.list
    puts "Active relayers: #{relayers.length}"
    relayers.first(3).each do |relayer|
      puts "  #{relayer.address}: #{relayer.packets_relayed} packets (#{relayer.status})"
    end

    # Register as a relayer
    puts "\nRegistering as relayer..."
    registration = @ibc.relayer.register(
      address: 'synor1relayer...',
      chains: %w[synor-mainnet cosmoshub-4 osmosis-1],
      commission: 0.1 # 0.1%
    )
    puts "  Registered: #{registration.relayer_id}"

    # Start relaying
    puts "\nStarting packet relay..."
    relay_config = {
      channels: %w[channel-0 channel-1],
      batch_size: 10,
      poll_interval: 5
    }

    # In production, this would run continuously
    pending_count = @ibc.relayer.get_pending_count(relay_config[:channels])
    puts "  Pending packets to relay: #{pending_count}"

    # Relay a batch
    relay_result = @ibc.relayer.relay_batch('channel-0', 5)
    puts "  Relayed: #{relay_result.packets_relayed}"
    puts "  Fees earned: #{relay_result.fees_earned}"

    # Get relayer earnings
    earnings = @ibc.relayer.get_earnings('synor1relayer...')
    puts "\nRelayer earnings:"
    puts "  Total earned: #{earnings.total_earned}"
    puts "  Packets relayed: #{earnings.packets_relayed}"
    puts "  Success rate: #{format('%.1f', earnings.success_rate)}%"
    puts
  end

  def run_monitoring_example
    puts '=== Connection Monitoring ==='

    # Get connection health
    connections = @ibc.monitoring.get_connections
    puts 'Connection health:'
    connections.each do |conn|
      health_icon = conn.healthy? ? '✓' : '✗'
      puts "  [#{health_icon}] #{conn.connection_id}: #{conn.chain_a} <-> #{conn.chain_b}"
      puts "      Latency: #{conn.latency}ms, Uptime: #{format('%.1f', conn.uptime)}%"
    end

    # Get channel metrics
    metrics = @ibc.monitoring.get_channel_metrics('channel-0')
    puts "\nChannel metrics:"
    puts "  Throughput: #{metrics.packets_per_hour}/hour"
    puts "  Avg latency: #{metrics.avg_latency_ms}ms"
    puts "  Success rate: #{format('%.1f', metrics.success_rate)}%"
    puts "  Volume 24h: #{metrics.volume_24h}"

    # Subscribe to events (in production)
    puts "\nEvent subscription example:"
    puts '  Subscribing to packet events...'
    # @ibc.monitoring.subscribe('channel-0') do |event|
    #   puts "  Event: #{event.type} - #{event.data}"
    # end

    # Get alerts
    alerts = @ibc.monitoring.get_alerts
    puts "\nActive alerts: #{alerts.length}"
    alerts.each do |alert|
      puts "  [#{alert.severity}] #{alert.message}"
      puts "    Channel: #{alert.channel_id}, Time: #{alert.timestamp}"
    end
    puts
  end
end

# Main execution
if __FILE__ == $PROGRAM_NAME
  # Initialize client
  api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key')
  config = Synor::Ibc::Config.new(
    api_key: api_key,
    endpoint: 'https://ibc.synor.io/v1',
    timeout: 60,
    retries: 3,
    debug: false,
    default_timeout: 1800 # 30 minutes
  )

  ibc = Synor::Ibc::Client.new(config)
  example = IbcExample.new(ibc)

  begin
    # Check service health
    healthy = ibc.health_check
    puts "Service healthy: #{healthy}\n\n"

    # Run examples
    example.run_chains_example
    example.run_channels_example
    example.run_transfer_example
    example.run_packet_example
    example.run_relayer_example
    example.run_monitoring_example
  rescue StandardError => e
    warn "Error: #{e.message}"
    exit 1
  end
end
