package io.synor.examples

import io.synor.dex.*
import io.synor.dex.types.*
import kotlinx.coroutines.runBlocking
import java.math.BigDecimal

/**
 * Synor DEX SDK Examples for Kotlin
 *
 * Demonstrates decentralized exchange operations:
 * - Spot trading (limit/market orders)
 * - Perpetual futures trading
 * - Liquidity provision (AMM pools)
 * - Order book management
 * - Portfolio tracking
 */
fun main() = runBlocking {
    // Initialize client
    val config = DexConfig(
        apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
        endpoint = "https://dex.synor.io/v1",
        timeout = 30_000,
        retries = 3,
        debug = false,
        defaultMarket = "SYN-USDC"
    )

    val dex = SynorDex(config)

    try {
        // Check service health
        val healthy = dex.healthCheck()
        println("Service healthy: $healthy\n")

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

suspend fun marketsExample(dex: SynorDex) {
    println("=== Markets ===")

    // Get all markets
    val markets = dex.markets.list()
    println("Available markets: ${markets.size}")

    markets.take(5).forEach { market ->
        println("\n  ${market.symbol}:")
        println("    Base: ${market.baseAsset}, Quote: ${market.quoteAsset}")
        println("    Price: ${market.lastPrice}")
        println("    24h Volume: ${market.volume24h}")
        println("    24h Change: ${market.change24h}%")
        println("    Status: ${market.status}")
    }

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

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

    println()
}

suspend fun spotTradingExample(dex: SynorDex) {
    println("=== Spot Trading ===")

    // Place a limit order
    println("Placing limit buy order...")
    val limitOrder = dex.spot.placeOrder(
        OrderRequest(
            market = "SYN-USDC",
            side = OrderSide.BUY,
            orderType = OrderType.LIMIT,
            price = "1.50",
            quantity = "100",
            timeInForce = TimeInForce.GTC
        )
    )

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

    // Place a market order
    println("\nPlacing market sell order...")
    val marketOrder = dex.spot.placeOrder(
        OrderRequest(
            market = "SYN-USDC",
            side = OrderSide.SELL,
            orderType = OrderType.MARKET,
            quantity = "50"
        )
    )

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

    // Get order status
    val status = dex.spot.getOrder(limitOrder.orderId)
    println("\nOrder status:")
    println("  Status: ${status.status}")
    println("  Filled: ${status.filledQuantity} / ${status.quantity}")
    println("  Remaining: ${status.remainingQuantity}")

    // Cancel order
    println("\nCancelling order...")
    dex.spot.cancelOrder(limitOrder.orderId)
    println("Order cancelled successfully")

    // Get open orders
    val openOrders = dex.spot.getOpenOrders("SYN-USDC")
    println("\nOpen orders: ${openOrders.size}")

    // Get trade history
    val trades = dex.spot.getTradeHistory("SYN-USDC", limit = 10)
    println("\nRecent trades: ${trades.size}")
    trades.take(3).forEach { trade ->
        println("  ${trade.side} ${trade.quantity} @ ${trade.price} (${trade.timestamp})")
    }

    println()
}

suspend fun perpsTradingExample(dex: SynorDex) {
    println("=== Perpetual Futures Trading ===")

    // Get available perps markets
    val perpsMarkets = dex.perps.listMarkets()
    println("Available perps markets: ${perpsMarkets.size}")

    perpsMarkets.take(3).forEach { market ->
        println("  ${market.symbol}: ${market.markPrice} (funding: ${market.fundingRate}%)")
    }

    // Open a long position
    println("\nOpening long position...")
    val position = dex.perps.openPosition(
        PerpsOrderRequest(
            market = "SYN-USDC-PERP",
            side = OrderSide.BUY,
            orderType = OrderType.LIMIT,
            price = "1.50",
            size = "1000",
            leverage = 10,
            reduceOnly = false
        )
    )

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

    // Get position details
    val details = dex.perps.getPosition(position.positionId)
    println("\nPosition details:")
    println("  Unrealized PnL: ${details.unrealizedPnL}")
    println("  Margin: ${details.margin}")
    println("  Margin ratio: ${details.marginRatio}%")

    // Set stop loss and take profit
    println("\nSetting stop loss and take profit...")
    dex.perps.setStopLoss(position.positionId, "1.40")
    println("Stop loss set at 1.40")

    dex.perps.setTakeProfit(position.positionId, "1.80")
    println("Take profit set at 1.80")

    // Close position
    println("\nClosing position...")
    val closeResult = dex.perps.closePosition(position.positionId)
    println("Position closed:")
    println("  Realized PnL: ${closeResult.realizedPnL}")
    println("  Close price: ${closeResult.closePrice}")

    // Get all positions
    val positions = dex.perps.getPositions()
    println("\nOpen positions: ${positions.size}")

    // Get funding history
    val funding = dex.perps.getFundingHistory("SYN-USDC-PERP", limit = 10)
    println("Funding payments: ${funding.size}")

    println()
}

suspend fun liquidityExample(dex: SynorDex) {
    println("=== Liquidity Provision ===")

    // Get available pools
    val pools = dex.liquidity.listPools()
    println("Available pools: ${pools.size}")

    pools.take(3).forEach { pool ->
        println("\n  ${pool.name}:")
        println("    TVL: \$${pool.tvl}")
        println("    APR: ${pool.apr}%")
        println("    Volume 24h: \$${pool.volume24h}")
        println("    Fee tier: ${pool.feeTier}%")
    }

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

    // Add liquidity
    println("\nAdding liquidity...")
    val addResult = dex.liquidity.addLiquidity(
        AddLiquidityRequest(
            pool = "SYN-USDC",
            amount0 = "100",
            amount1 = "150",
            slippageBps = 50 // 0.5%
        )
    )

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

    // Get LP positions
    val lpPositions = dex.liquidity.getPositions()
    println("\nLP positions: ${lpPositions.size}")
    lpPositions.forEach { pos ->
        println("  ${pos.pool}: ${pos.lpTokens} LP tokens (value: \$${pos.value})")
    }

    // Claim fees
    println("\nClaiming fees...")
    val fees = dex.liquidity.claimFees(addResult.positionId)
    println("Fees claimed:")
    println("  Token0: ${fees.amount0}")
    println("  Token1: ${fees.amount1}")

    // Remove liquidity
    println("\nRemoving liquidity...")
    val removeResult = dex.liquidity.removeLiquidity(
        RemoveLiquidityRequest(
            positionId = addResult.positionId,
            lpTokens = addResult.lpTokens,
            slippageBps = 50
        )
    )

    println("Liquidity removed:")
    println("  Token0 received: ${removeResult.amount0}")
    println("  Token1 received: ${removeResult.amount1}")

    println()
}

suspend fun orderbookExample(dex: SynorDex) {
    println("=== Order Book ===")

    // Get order book snapshot
    val orderbook = dex.orderbook.getSnapshot("SYN-USDC", depth = 10)

    println("Order book for SYN-USDC:")
    println("\nAsks (sells):")
    orderbook.asks.take(5).forEach { ask ->
        println("  ${ask.quantity} @ ${ask.price}")
    }

    println("\nBids (buys):")
    orderbook.bids.take(5).forEach { bid ->
        println("  ${bid.quantity} @ ${bid.price}")
    }

    println("\nSpread: ${orderbook.spread} (${orderbook.spreadPercent}%)")
    println("Mid price: ${orderbook.midPrice}")

    // Get recent trades
    val recentTrades = dex.orderbook.getRecentTrades("SYN-USDC", limit = 10)
    println("\nRecent trades:")
    recentTrades.take(5).forEach { trade ->
        println("  ${trade.side} ${trade.quantity} @ ${trade.price}")
    }

    println()
}

suspend fun portfolioExample(dex: SynorDex) {
    println("=== Portfolio ===")

    // Get portfolio overview
    val portfolio = dex.portfolio.getOverview()

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

    // Get balances
    val balances = dex.portfolio.getBalances()
    println("\nBalances:")
    balances.forEach { balance ->
        println("  ${balance.asset}: ${balance.total} (available: ${balance.available}, in orders: ${balance.inOrders})")
    }

    // Get PnL history
    val pnlHistory = dex.portfolio.getPnLHistory(days = 30) // Last 30 days
    println("\nPnL history (last ${pnlHistory.size} days):")
    if (pnlHistory.isNotEmpty()) {
        println("  Total PnL: \$${pnlHistory.last().cumulativePnL}")
    }

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

    println()
}
