/// Synor DEX SDK Examples for Flutter/Dart
///
/// Demonstrates decentralized exchange operations:
/// - Spot trading (limit/market orders)
/// - Perpetual futures trading
/// - Liquidity provision (AMM pools)
/// - Order book management
/// - Portfolio tracking
library;

import 'dart:io';
import 'dart:math';
import 'package:synor_dex/synor_dex.dart';

Future<void> main() async {
  // Initialize client
  final config = DexConfig(
    apiKey: Platform.environment['SYNOR_API_KEY'] ?? 'your-api-key',
    endpoint: 'https://dex.synor.io/v1',
    timeout: const Duration(seconds: 30),
    retries: 3,
    debug: false,
    defaultMarket: 'SYN-USDC',
  );

  final dex = SynorDex(config);

  try {
    // Check service health
    final healthy = await dex.healthCheck();
    print('Service healthy: $healthy\n');

    // Run examples
    await marketsExample(dex);
    await spotTradingExample(dex);
    await perpsTradingExample(dex);
    await liquidityExample(dex);
    await orderbookExample(dex);
    await portfolioExample(dex);
  } finally {
    await dex.close();
  }
}

Future<void> marketsExample(SynorDex dex) async {
  print('=== Markets ===');

  // Get all markets
  final markets = await dex.markets.list();
  print('Available markets: ${markets.length}');

  for (final market in markets.take(5)) {
    print('\n  ${market.symbol}:');
    print('    Base: ${market.baseAsset}, Quote: ${market.quoteAsset}');
    print('    Price: ${market.lastPrice}');
    print('    24h Volume: ${market.volume24h}');
    print('    24h Change: ${market.change24h}%');
    print('    Status: ${market.status}');
  }

  // Get specific market
  final market = await dex.markets.get('SYN-USDC');
  print('\nSYN-USDC details:');
  print('  Min order size: ${market.minOrderSize}');
  print('  Tick size: ${market.tickSize}');
  print('  Maker fee: ${market.makerFee}%');
  print('  Taker fee: ${market.takerFee}%');

  // Get market statistics
  final stats = await dex.markets.getStats('SYN-USDC');
  print('\nMarket statistics:');
  print('  High 24h: ${stats.high24h}');
  print('  Low 24h: ${stats.low24h}');
  print('  Open interest: ${stats.openInterest}');
  print('  Funding rate: ${stats.fundingRate}%');

  print('');
}

Future<void> spotTradingExample(SynorDex dex) async {
  print('=== Spot Trading ===');

  // Place a limit order
  print('Placing limit buy order...');
  final limitOrder = await dex.spot.placeOrder(OrderRequest(
    market: 'SYN-USDC',
    side: OrderSide.buy,
    orderType: OrderType.limit,
    price: '1.50',
    quantity: '100',
    timeInForce: TimeInForce.gtc,
  ));

  print('Limit order placed:');
  print('  Order ID: ${limitOrder.orderId}');
  print('  Status: ${limitOrder.status}');
  print('  Price: ${limitOrder.price}');
  print('  Quantity: ${limitOrder.quantity}');

  // Place a market order
  print('\nPlacing market sell order...');
  final marketOrder = await dex.spot.placeOrder(OrderRequest(
    market: 'SYN-USDC',
    side: OrderSide.sell,
    orderType: OrderType.market,
    quantity: '50',
  ));

  print('Market order executed:');
  print('  Order ID: ${marketOrder.orderId}');
  print('  Status: ${marketOrder.status}');
  print('  Filled: ${marketOrder.filledQuantity}');
  print('  Avg price: ${marketOrder.averagePrice}');

  // Get order status
  final status = await dex.spot.getOrder(limitOrder.orderId);
  print('\nOrder status:');
  print('  Status: ${status.status}');
  print('  Filled: ${status.filledQuantity} / ${status.quantity}');
  print('  Remaining: ${status.remainingQuantity}');

  // Cancel order
  print('\nCancelling order...');
  await dex.spot.cancelOrder(limitOrder.orderId);
  print('Order cancelled successfully');

  // Get open orders
  final openOrders = await dex.spot.getOpenOrders('SYN-USDC');
  print('\nOpen orders: ${openOrders.length}');

  // Get trade history
  final trades = await dex.spot.getTradeHistory('SYN-USDC', limit: 10);
  print('\nRecent trades: ${trades.length}');
  for (final trade in trades.take(3)) {
    print('  ${trade.side} ${trade.quantity} @ ${trade.price} (${trade.timestamp})');
  }

  print('');
}

Future<void> perpsTradingExample(SynorDex dex) async {
  print('=== Perpetual Futures Trading ===');

  // Get available perps markets
  final perpsMarkets = await dex.perps.listMarkets();
  print('Available perps markets: ${perpsMarkets.length}');

  for (final market in perpsMarkets.take(3)) {
    print('  ${market.symbol}: ${market.markPrice} (funding: ${market.fundingRate}%)');
  }

  // Open a long position
  print('\nOpening long position...');
  final position = await dex.perps.openPosition(PerpsOrderRequest(
    market: 'SYN-USDC-PERP',
    side: OrderSide.buy,
    orderType: OrderType.limit,
    price: '1.50',
    size: '1000',
    leverage: 10,
    reduceOnly: false,
  ));

  print('Position opened:');
  print('  Position ID: ${position.positionId}');
  print('  Size: ${position.size}');
  print('  Entry price: ${position.entryPrice}');
  print('  Leverage: ${position.leverage}x');
  print('  Liquidation price: ${position.liquidationPrice}');

  // Get position details
  final details = await dex.perps.getPosition(position.positionId);
  print('\nPosition details:');
  print('  Unrealized PnL: ${details.unrealizedPnL}');
  print('  Margin: ${details.margin}');
  print('  Margin ratio: ${details.marginRatio}%');

  // Set stop loss and take profit
  print('\nSetting stop loss and take profit...');
  await dex.perps.setStopLoss(position.positionId, '1.40');
  print('Stop loss set at 1.40');

  await dex.perps.setTakeProfit(position.positionId, '1.80');
  print('Take profit set at 1.80');

  // Close position
  print('\nClosing position...');
  final closeResult = await dex.perps.closePosition(position.positionId);
  print('Position closed:');
  print('  Realized PnL: ${closeResult.realizedPnL}');
  print('  Close price: ${closeResult.closePrice}');

  // Get all positions
  final positions = await dex.perps.getPositions();
  print('\nOpen positions: ${positions.length}');

  // Get funding history
  final funding = await dex.perps.getFundingHistory('SYN-USDC-PERP', limit: 10);
  print('Funding payments: ${funding.length}');

  print('');
}

Future<void> liquidityExample(SynorDex dex) async {
  print('=== Liquidity Provision ===');

  // Get available pools
  final pools = await dex.liquidity.listPools();
  print('Available pools: ${pools.length}');

  for (final pool in pools.take(3)) {
    print('\n  ${pool.name}:');
    print('    TVL: \$${pool.tvl}');
    print('    APR: ${pool.apr}%');
    print('    Volume 24h: \$${pool.volume24h}');
    print('    Fee tier: ${pool.feeTier}%');
  }

  // Get pool details
  final pool = await dex.liquidity.getPool('SYN-USDC');
  print('\nSYN-USDC pool details:');
  print('  Token0: ${pool.token0.symbol} (${pool.token0Reserve})');
  print('  Token1: ${pool.token1.symbol} (${pool.token1Reserve})');
  print('  Price: ${pool.price}');
  print('  Total LP tokens: ${pool.totalLPTokens}');

  // Add liquidity
  print('\nAdding liquidity...');
  final addResult = await dex.liquidity.addLiquidity(AddLiquidityRequest(
    pool: 'SYN-USDC',
    amount0: '100',
    amount1: '150',
    slippageBps: 50, // 0.5%
  ));

  print('Liquidity added:');
  print('  LP tokens received: ${addResult.lpTokens}');
  print('  Position ID: ${addResult.positionId}');
  print('  Share of pool: ${addResult.shareOfPool}%');

  // Get LP positions
  final lpPositions = await dex.liquidity.getPositions();
  print('\nLP positions: ${lpPositions.length}');
  for (final pos in lpPositions) {
    print('  ${pos.pool}: ${pos.lpTokens} LP tokens (value: \$${pos.value})');
  }

  // Claim fees
  print('\nClaiming fees...');
  final fees = await dex.liquidity.claimFees(addResult.positionId);
  print('Fees claimed:');
  print('  Token0: ${fees.amount0}');
  print('  Token1: ${fees.amount1}');

  // Remove liquidity
  print('\nRemoving liquidity...');
  final removeResult = await dex.liquidity.removeLiquidity(RemoveLiquidityRequest(
    positionId: addResult.positionId,
    lpTokens: addResult.lpTokens,
    slippageBps: 50,
  ));

  print('Liquidity removed:');
  print('  Token0 received: ${removeResult.amount0}');
  print('  Token1 received: ${removeResult.amount1}');

  print('');
}

Future<void> orderbookExample(SynorDex dex) async {
  print('=== Order Book ===');

  // Get order book snapshot
  final orderbook = await dex.orderbook.getSnapshot('SYN-USDC', depth: 10);

  print('Order book for SYN-USDC:');
  print('\nAsks (sells):');
  for (final ask in orderbook.asks.take(5)) {
    print('  ${ask.quantity} @ ${ask.price}');
  }

  print('\nBids (buys):');
  for (final bid in orderbook.bids.take(5)) {
    print('  ${bid.quantity} @ ${bid.price}');
  }

  print('\nSpread: ${orderbook.spread} (${orderbook.spreadPercent}%)');
  print('Mid price: ${orderbook.midPrice}');

  // Get recent trades
  final recentTrades = await dex.orderbook.getRecentTrades('SYN-USDC', limit: 10);
  print('\nRecent trades:');
  for (final trade in recentTrades.take(5)) {
    print('  ${trade.side} ${trade.quantity} @ ${trade.price}');
  }

  // Subscribe to orderbook updates (simulated)
  print('\nSubscribing to orderbook updates...');
  final subscription = dex.orderbook.subscribe('SYN-USDC');

  // Process a few updates
  int count = 0;
  await for (final update in subscription) {
    print('  Update: ${update.side} ${update.quantity} @ ${update.price}');
    count++;
    if (count >= 3) break;
  }

  print('');
}

Future<void> portfolioExample(SynorDex dex) async {
  print('=== Portfolio ===');

  // Get portfolio overview
  final portfolio = await dex.portfolio.getOverview();

  print('Portfolio overview:');
  print('  Total value: \$${portfolio.totalValue}');
  print('  Available balance: \$${portfolio.availableBalance}');
  print('  In orders: \$${portfolio.inOrders}');
  print('  In positions: \$${portfolio.inPositions}');
  print('  Unrealized PnL: \$${portfolio.unrealizedPnL}');

  // Get balances
  final balances = await dex.portfolio.getBalances();
  print('\nBalances:');
  for (final balance in balances) {
    print('  ${balance.asset}: ${balance.total} (available: ${balance.available}, in orders: ${balance.inOrders})');
  }

  // Get PnL history
  final pnlHistory = await dex.portfolio.getPnLHistory(days: 30); // Last 30 days
  print('\nPnL history (last ${pnlHistory.length} days):');
  if (pnlHistory.isNotEmpty) {
    print('  Total PnL: \$${pnlHistory.last.cumulativePnL}');
  }

  // Get trade statistics
  final stats = await dex.portfolio.getStats();
  print('\nTrade statistics:');
  print('  Total trades: ${stats.totalTrades}');
  print('  Win rate: ${stats.winRate}%');
  print('  Avg profit: \$${stats.avgProfit}');
  print('  Avg loss: \$${stats.avgLoss}');
  print('  Best trade: \$${stats.bestTrade}');
  print('  Worst trade: \$${stats.worstTrade}');

  print('');
}
