using Binance.Net.Enums;
using Binance.Net.Interfaces;
using Binance.Net.Objects.Models.Futures;
using CryptoExchange.Net.Objects;
using Managing.Core;
using Managing.Domain.Candles;
using Managing.Domain.Trades;
using static Managing.Common.Enums;

namespace Managing.Infrastructure.Exchanges.Helpers
{
    public static class BinanceHelpers
    {
        public static Trade Map(BinanceFuturesOrder data)
        {
            if (data == null)
                return null;

            return new Trade(data.CreateTime,
                (data.Side == OrderSide.Buy) ? TradeDirection.Long : TradeDirection.Short,
                (TradeStatus)data.Status, (TradeType)data.OriginalType, MiscExtensions.ParseEnum<Ticker>(data.Symbol),
                data.Quantity, data.AveragePrice, 1,
                data.ClientOrderId, "");
        }

        public static FuturesOrderType BinanceOrderTypeMap(TradeType tradeType)
        {
            switch (tradeType)
            {
                case TradeType.Limit:
                    return FuturesOrderType.Limit;
                case TradeType.Market:
                    return FuturesOrderType.Market;
                case TradeType.StopMarket:
                    return FuturesOrderType.StopMarket;
                case TradeType.StopLossLimit:
                    return FuturesOrderType.Stop;
                default:
                    return FuturesOrderType.Limit;
            }
        }

        public static TradeType BinanceOrderTradeType(FuturesOrderType orderType)
        {
            switch (orderType)
            {
                case FuturesOrderType.Stop:
                case FuturesOrderType.Limit:
                    return TradeType.Limit;
                case FuturesOrderType.Market:
                    return TradeType.Market;
                case FuturesOrderType.StopMarket:
                    return TradeType.StopMarket;
                default:
                    return TradeType.Limit;
            }
        }

        public static Trade Map(WebCallResult<BinanceFuturesPlacedOrder> result, decimal? leverage = null)
        {
            var data = result.Data;

            if (data == null)
            {
                return new Trade(DateTime.Now, TradeDirection.None,
                    TradeStatus.Cancelled, TradeType.Market, Ticker.BTC, 0, 0, 0,
                    "", result.Error?.Message);
            }

            return new Trade(DateTime.Now, TradeDirection.None,
                TradeStatus.Cancelled, TradeType.Market, Ticker.BTC, 0, 0, 0,
                "", result.Error?.Message);
        }

        public static Candle Map(IBinanceKline binanceKline, Ticker ticker, TradingExchanges exchange)
        {
            return new Candle
            {
                Date = binanceKline.CloseTime,
                Volume = binanceKline.Volume,
                Close = binanceKline.ClosePrice,
                High = binanceKline.HighPrice,
                Low = binanceKline.LowPrice,
                Open = binanceKline.OpenPrice,
                Ticker = ticker.ToString(),
                OpenTime = binanceKline.OpenTime,
                Exchange = exchange
            };
        }

        internal static KlineInterval Map(Timeframe interval) => interval switch
        {
            Timeframe.FiveMinutes => KlineInterval.FiveMinutes,
            Timeframe.FifteenMinutes => KlineInterval.FifteenMinutes,
            Timeframe.ThirtyMinutes => KlineInterval.ThirtyMinutes,
            Timeframe.OneHour => KlineInterval.OneHour,
            Timeframe.FourHour => KlineInterval.FourHour,
            Timeframe.OneDay => KlineInterval.OneDay,
            _ => throw new NotImplementedException(),
        };

        public static string ToBinanceTicker(Ticker ticker)
        {
            switch (ticker)
            {
                case Ticker.ADA:
                    return "ADAUSDT";
                case Ticker.ALGO:
                    return "ALGOUSDT";
                case Ticker.ATOM:
                    return "ATOMUSDT";
                case Ticker.AVAX:
                    return "AVAXUSDT";
                case Ticker.BNB:
                    return "BNBUSDT";
                case Ticker.BTC:
                    return "BTCUSDT";
                case Ticker.CRV:
                    return "CRVUSDT";
                case Ticker.DOGE:
                    return "DOGEUSDT";
                case Ticker.DOT:
                    return "DOTUSDT";
                case Ticker.DYDX:
                    return "DYDXUSDT";
                case Ticker.ETC:
                    return "ETCUSDT";
                case Ticker.ETH:
                    return "ETHUSDT";
                case Ticker.FTM:
                    return "FTMUSDT";
                case Ticker.GALA:
                    return "GALAUSDT";
                case Ticker.GRT:
                    return "GRTUSDT";
                case Ticker.IMX:
                    return "IMXUSDT";
                case Ticker.KSM:
                    return "KSMUSDT";
                case Ticker.LINK:
                    return "LINKUSDT";
                case Ticker.LRC:
                    return "LRCUSDT";
                case Ticker.LTC:
                    return "LTCUSDT";
                case Ticker.MATIC:
                    return "MATICUSDT";
                case Ticker.MKR:
                    return "MKRUSDT";
                case Ticker.NEAR:
                    return "NEARUSDT";
                case Ticker.SAND:
                    return "SANDUSDT";
                case Ticker.SOL:
                    return "SOLUSDT";
                case Ticker.SRM:
                    return "SRMUSDT";
                case Ticker.SUSHI:
                    return "SUSHIUSDT";
                case Ticker.THETA:
                    return "THETAUSDT";
                case Ticker.UNI:
                    return "UNIUSDT";
                case Ticker.XMR:
                    return "XMRUSDT";
                case Ticker.XRP:
                    return "XRPUSDT";
                case Ticker.XTZ:
                    return "XTZUSDT";
                default:
                    break;
            }

            throw new NotImplementedException();
        }

        internal static object Map(WebCallResult<BinanceUsdFuturesOrder> binanceResult, decimal? leverage)
        {
            throw new NotImplementedException();
        }
    }

    public class BinanceFuturesPlacedOrder
    {
    }
}