using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text.Json.Serialization;

namespace Synor.Dex
{
    public enum PoolType { ConstantProduct, Stable, Concentrated }
    public enum PositionSide { Long, Short }
    public enum OrderType { Market, Limit, StopMarket, StopLimit, TakeProfit, TakeProfitLimit }
    public enum MarginType { Cross, Isolated }
    public enum TimeInForce { GTC, IOC, FOK, GTD }
    public enum OrderStatus { Pending, Open, PartiallyFilled, Filled, Cancelled, Expired }

    public class Token
    {
        public string Address { get; set; }
        public string Symbol { get; set; }
        public string Name { get; set; }
        public int Decimals { get; set; }
        public string TotalSupply { get; set; }
        public double? PriceUsd { get; set; }
        public string LogoUrl { get; set; }
        public bool Verified { get; set; }
    }

    public class Pool
    {
        public string Id { get; set; }
        public Token TokenA { get; set; }
        public Token TokenB { get; set; }
        public PoolType PoolType { get; set; }
        public string ReserveA { get; set; }
        public string ReserveB { get; set; }
        public double Fee { get; set; }
        public double TvlUsd { get; set; }
        public double Volume24h { get; set; }
        public double Apr { get; set; }
        public string LpTokenAddress { get; set; }
    }

    public class PoolFilter
    {
        public List<string> Tokens { get; set; }
        public double? MinTvl { get; set; }
        public double? MinVolume24h { get; set; }
        public bool? Verified { get; set; }
        public int? Limit { get; set; }
        public int? Offset { get; set; }
    }

    public class Quote
    {
        public string TokenIn { get; set; }
        public string TokenOut { get; set; }
        public string AmountIn { get; set; }
        public string AmountOut { get; set; }
        public double PriceImpact { get; set; }
        public List<string> Route { get; set; }
        public string Fee { get; set; }
        public string MinimumReceived { get; set; }
        public long ExpiresAt { get; set; }
    }

    public class QuoteParams
    {
        public string TokenIn { get; set; }
        public string TokenOut { get; set; }
        public BigInteger AmountIn { get; set; }
        public double? Slippage { get; set; }
    }

    public class SwapParams
    {
        public string TokenIn { get; set; }
        public string TokenOut { get; set; }
        public BigInteger AmountIn { get; set; }
        public BigInteger MinAmountOut { get; set; }
        public long? Deadline { get; set; }
        public string Recipient { get; set; }
    }

    public class SwapResult
    {
        public string TransactionHash { get; set; }
        public string AmountIn { get; set; }
        public string AmountOut { get; set; }
        public double EffectivePrice { get; set; }
        public string FeePaid { get; set; }
        public List<string> Route { get; set; }
    }

    public class AddLiquidityParams
    {
        public string TokenA { get; set; }
        public string TokenB { get; set; }
        public BigInteger AmountA { get; set; }
        public BigInteger AmountB { get; set; }
        public BigInteger? MinAmountA { get; set; }
        public BigInteger? MinAmountB { get; set; }
        public long? Deadline { get; set; }
    }

    public class RemoveLiquidityParams
    {
        public string Pool { get; set; }
        public BigInteger LpAmount { get; set; }
        public BigInteger? MinAmountA { get; set; }
        public BigInteger? MinAmountB { get; set; }
        public long? Deadline { get; set; }
    }

    public class LiquidityResult
    {
        public string TransactionHash { get; set; }
        public string AmountA { get; set; }
        public string AmountB { get; set; }
        public string LpTokens { get; set; }
        public double PoolShare { get; set; }
    }

    public class LPPosition
    {
        public string PoolId { get; set; }
        public string LpTokens { get; set; }
        public string TokenAAmount { get; set; }
        public string TokenBAmount { get; set; }
        public double ValueUsd { get; set; }
        public string UnclaimedFeesA { get; set; }
        public string UnclaimedFeesB { get; set; }
        public double ImpermanentLoss { get; set; }
    }

    public class PerpMarket
    {
        public string Symbol { get; set; }
        public string BaseAsset { get; set; }
        public string QuoteAsset { get; set; }
        public double IndexPrice { get; set; }
        public double MarkPrice { get; set; }
        public double FundingRate { get; set; }
        public long NextFundingTime { get; set; }
        public string OpenInterest { get; set; }
        public double Volume24h { get; set; }
        public int MaxLeverage { get; set; }
    }

    public class OpenPositionParams
    {
        public string Market { get; set; }
        public PositionSide Side { get; set; }
        public BigInteger Size { get; set; }
        public int Leverage { get; set; }
        public OrderType OrderType { get; set; }
        public double? LimitPrice { get; set; }
        public double? StopLoss { get; set; }
        public double? TakeProfit { get; set; }
        public MarginType MarginType { get; set; } = MarginType.Cross;
        public bool ReduceOnly { get; set; }
    }

    public class ClosePositionParams
    {
        public string Market { get; set; }
        public BigInteger? Size { get; set; }
        public OrderType OrderType { get; set; } = OrderType.Market;
        public double? LimitPrice { get; set; }
    }

    public class PerpPosition
    {
        public string Id { get; set; }
        public string Market { get; set; }
        public PositionSide Side { get; set; }
        public string Size { get; set; }
        public double EntryPrice { get; set; }
        public double MarkPrice { get; set; }
        public double LiquidationPrice { get; set; }
        public string Margin { get; set; }
        public int Leverage { get; set; }
        public string UnrealizedPnl { get; set; }
    }

    public class PerpOrder
    {
        public string Id { get; set; }
        public string Market { get; set; }
        public PositionSide Side { get; set; }
        public OrderType OrderType { get; set; }
        public string Size { get; set; }
        public double? Price { get; set; }
        public OrderStatus Status { get; set; }
    }

    public class FundingPayment
    {
        public string Market { get; set; }
        public string Amount { get; set; }
        public double Rate { get; set; }
        public string PositionSize { get; set; }
        public long Timestamp { get; set; }
    }

    public class FundingRateInfo
    {
        public double Rate { get; set; }
        public long NextTime { get; set; }
    }

    public class OrderBookEntry
    {
        public double Price { get; set; }
        public string Size { get; set; }
        public int Orders { get; set; }
    }

    public class OrderBook
    {
        public string Market { get; set; }
        public List<OrderBookEntry> Bids { get; set; }
        public List<OrderBookEntry> Asks { get; set; }
        public long Timestamp { get; set; }
    }

    public class LimitOrderParams
    {
        public string Market { get; set; }
        public string Side { get; set; }
        public double Price { get; set; }
        public BigInteger Size { get; set; }
        public TimeInForce TimeInForce { get; set; } = TimeInForce.GTC;
        public bool PostOnly { get; set; }
    }

    public class Order
    {
        public string Id { get; set; }
        public string Market { get; set; }
        public string Side { get; set; }
        public double Price { get; set; }
        public string Size { get; set; }
        public string FilledSize { get; set; }
        public OrderStatus Status { get; set; }
        public TimeInForce TimeInForce { get; set; }
        public bool PostOnly { get; set; }
    }

    public class Farm
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public Token StakeToken { get; set; }
        public List<Token> RewardTokens { get; set; }
        public double TvlUsd { get; set; }
        public double Apr { get; set; }
    }

    public class StakeParams
    {
        public string Farm { get; set; }
        public BigInteger Amount { get; set; }
    }

    public class FarmPosition
    {
        public string FarmId { get; set; }
        public string StakedAmount { get; set; }
        public List<string> PendingRewards { get; set; }
        public long StakedAt { get; set; }
    }

    public class ClaimRewardsResult
    {
        public string Amount { get; set; }
        public string TransactionHash { get; set; }
    }

    public class OHLCV
    {
        public long Timestamp { get; set; }
        public double Open { get; set; }
        public double High { get; set; }
        public double Low { get; set; }
        public double Close { get; set; }
        public double Volume { get; set; }
    }

    public class TradeHistory
    {
        public string Id { get; set; }
        public string Market { get; set; }
        public string Side { get; set; }
        public double Price { get; set; }
        public string Size { get; set; }
        public long Timestamp { get; set; }
        public string Maker { get; set; }
        public string Taker { get; set; }
    }

    public class VolumeStats
    {
        public double Volume24h { get; set; }
        public double Volume7d { get; set; }
        public double Volume30d { get; set; }
        public int Trades24h { get; set; }
    }

    public class TVLStats
    {
        public double TotalTvl { get; set; }
        public double PoolsTvl { get; set; }
        public double FarmsTvl { get; set; }
        public double PerpsTvl { get; set; }
    }
}
