using Managing.Common;
using Nethereum.Util;

namespace Managing.Infrastructure.Evm.Services.Gmx;

public static class TokenV2Service
{
    public static List<GmxToken> TOKENS { get; set; } = new List<GmxToken>
    {
        new GmxToken
        {
            Name = "Ethereum",
            Symbol = "ETH",
            Decimals = 18,
            PriceDecimals = 12,
            Address = AddressUtil.ZERO_ADDRESS,
            IsNative = true,
            IsShortable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/279/small/ethereum.png?1595348880",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/ethereum",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Wrapped Ethereum",
            Symbol = "WETH",
            Decimals = 18,
            PriceDecimals = 12,
            Address = Constants.GMX.TokenAddress.WETH,
            IsWrapped = true,
            BaseSymbol = "ETH",
            ImageUrl = "https://assets.coingecko.com/coins/images/2518/thumb/weth.png?1628852295",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/ethereum",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Wrapped Stacked Ethereum",
            Symbol = "WSTETH",
            Decimals = 18,
            PriceDecimals = 12,
            Address = Constants.GMX.TokenAddress.WSTETH,
            IsWrapped = true,
            BaseSymbol = "wstETH",
            ImageUrl = "https://assets.coingecko.com/coins/images/2518/thumb/wsteth.png?1628852295",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/ethereum",
        },
        new GmxToken
        {
            Name = "Bitcoin (WBTC)",
            Symbol = "BTC",
            AssetSymbol = "WBTC",
            Decimals = 8,
            PriceDecimals = 22,
            Address = Constants.GMX.TokenAddress.WBTC,
            IsShortable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/26115/thumb/btcb.png?1655921693",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/wrapped-bitcoin",
            ExplorerUrl = "https://arbiscan.io/address/0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Arbitrum",
            Symbol = "ARB",
            Decimals = 18,
            PriceDecimals = 3,
            Address = Constants.GMX.TokenAddress.ARB,
            ImageUrl =
                "https://assets.coingecko.com/coins/images/16547/small/photo_2023-03-29_21.47.00.jpeg?1680097630",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/arbitrum",
            ExplorerUrl = "https://arbiscan.io/token/0x912ce59144191c1204e64559fe8253a0e49e6548"
        },
        new GmxToken
        {
            Name = "Wrapped SOL (Wormhole)",
            Symbol = "SOL",
            AssetSymbol = "WSOL (Wormhole)",
            Decimals = 9,
            Address = Constants.GMX.TokenAddress.SOL,
            ImageUrl = "https://assets.coingecko.com/coins/images/4128/small/solana.png?1640133422",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/solana",
            ExplorerUrl = "https://arbiscan.io/token/0x2bCc6D6CdBbDC0a4071e48bb3B969b06B3330c07",
        },
        new GmxToken
        {
            Name = "Chainlink",
            Symbol = "LINK",
            Decimals = 18,
            PriceDecimals = 3,
            Address = Constants.GMX.TokenAddress.LINK,
            IsStable = false,
            IsShortable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/877/thumb/chainlink-new-logo.png?1547034700",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/chainlink",
            ExplorerUrl = "https://arbiscan.io/token/0xf97f4df75117a78c1a5a0dbb814af92458539fb4",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Uniswap",
            Symbol = "UNI",
            Decimals = 18,
            PriceDecimals = 3,
            Address = Constants.GMX.TokenAddress.UNI,
            IsStable = false,
            IsShortable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/12504/thumb/uniswap-uni.png?1600306604",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/uniswap",
            ExplorerUrl = "https://arbiscan.io/token/0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Bridged USDC (USDC.e)",
            Symbol = "USDC.e",
            Decimals = 6,
            Address = Constants.GMX.TokenAddress.USDCE,
            IsStable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/6319/thumb/USD_Coin_icon.png?1547042389",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/bridged-usdc-arbitrum",
            ExplorerUrl = "https://arbiscan.io/token/0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "USD Coin",
            Symbol = "USDC",
            Decimals = 6,
            Address = Constants.GMX.TokenAddress.USDC,
            IsStable = true,
            IsV1Available = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/6319/thumb/USD_Coin_icon.png?1547042389",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/usd-coin",
            ExplorerUrl = "https://arbiscan.io/address/0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
        },
        new GmxToken
        {
            Name = "Tether",
            Symbol = "USDT",
            Decimals = 6,
            Address = Constants.GMX.TokenAddress.USDT,
            IsStable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/325/thumb/Tether-logo.png?1598003707",
            ExplorerUrl = "https://arbiscan.io/address/0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/tether",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Dai",
            Symbol = "DAI",
            Decimals = 18,
            Address = Constants.GMX.TokenAddress.DAI,
            IsStable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/9956/thumb/4943.png?1636636734",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/dai",
            ExplorerUrl = "https://arbiscan.io/token/0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "USDe",
            Symbol = "USDe",
            Decimals = 18,
            Address = Constants.GMX.TokenAddress.USDE,
            IsStable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/9956/thumb/4943.png?1636636734",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/usde",
            ExplorerUrl = "https://arbiscan.io/token/0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
        },
        new GmxToken
        {
            Name = "Frax",
            Symbol = "FRAX",
            Decimals = 18,
            Address = Constants.GMX.TokenAddress.FRAX,
            IsStable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/13422/small/frax_logo.png?1608476506",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/frax",
            ExplorerUrl = "https://arbiscan.io/token/0x17fc002b466eec40dae837fc4be5c67993ddbd6f",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Magic Internet Money",
            Symbol = "MIM",
            Decimals = 18,
            Address = Constants.GMX.TokenAddress.MIM,
            IsStable = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/magic-internet-money",
            ExplorerUrl = "https://arbiscan.io/token/0xFEa7a6a0B346362BF88A9e4A88416B77a57D6c2A",
            IsV1Available = true
        },
        new GmxToken
        {
            Name = "Bitcoin",
            Symbol = "BTC",
            Decimals = 8,
            Address = Constants.GMX.TokenAddress.BTC,
            IsSynthetic = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/1/small/bitcoin.png?1547033579",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/bitcoin",
        },
        new GmxToken()
        {
            Name = "DogeCoin",
            Symbol = "DOGE",
            Decimals = 8,
            PriceDecimals = 4,
            Address = Constants.GMX.TokenAddress.DOGE,
            IsSynthetic = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/5/small/dogecoin.png?1547792256",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/dogecoin",
        },
        new GmxToken
        {
            Name = "Litecoin",
            Symbol = "LTC",
            Decimals = 8,
            Address = Constants.GMX.TokenAddress.LTC,
            IsSynthetic = true,
            ImageUrl = "https://assets.coingecko.com/coins/images/2/small/litecoin.png?1547033580",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/litecoin",
        },
        new GmxToken
        {
            Name = "XRP",
            Symbol = "XRP",
            Decimals = 6,
            PriceDecimals = 4,
            Address = Constants.GMX.TokenAddress.XRP,
            ImageUrl = "https://assets.coingecko.com/coins/images/44/small/xrp-symbol-white-128.png?1605778731",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/xrp",
            IsSynthetic = true,
        },
        new GmxToken
        {
            Name = "GMX",
            Symbol = "GMX",
            Address =
                Constants.GMX.TokenAddress.GMX,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/18323/small/arbit.png?1631532468",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/gmx",
            ExplorerUrl = "https://arbiscan.io/address/0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a",
            IsPlatform = true
        },
        new GmxToken
        {
            Name = "Wrapped BNB (LayerZero)",
            Symbol = "BNB",
            AssetSymbol = "WBNB (LayerZero)",
            Address = Constants.GMX.TokenAddress.WBNB,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/825/standard/bnb-icon2_2x.png?1696501970",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/bnb",
        },
        new GmxToken
        {
            Name = "Cosmos",
            Symbol = "ATOM",
            AssetSymbol = "ATOM",
            Address = Constants.GMX.TokenAddress.ATOM,
            Decimals = 6,
            ImageUrl = "https://assets.coingecko.com/coins/images/1481/standard/cosmos_hub.png?1696502525",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/cosmos-hub",
            IsSynthetic = true
        },
        new GmxToken
        {
            Name = "Near",
            Symbol = "NEAR",
            AssetSymbol = "NEAR",
            Address = Constants.GMX.TokenAddress.NEAR,
            Decimals = 24,
            ImageUrl = "https://assets.coingecko.com/coins/images/10365/standard/near.jpg?1696510367",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/near",
            IsSynthetic = true
        },
        new GmxToken
        {
            Name = "Aave",
            Symbol = "AAVE",
            AssetSymbol = "AAVE",
            Address = Constants.GMX.TokenAddress.AAVE,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/12645/standard/AAVE.png?1696512452",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/aave"
        },
        new GmxToken
        {
            Name = "Wrapped AVAX (Wormhole)",
            Symbol = "AVAX",
            AssetSymbol = "WAVAX (Wormhole)",
            Address = Constants.GMX.TokenAddress.AVAX,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/12559/small/coin-round-red.png?1604021818",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/avalanche"
        },
        new GmxToken
        {
            Name = "Optimism",
            Symbol = "OP",
            Address = Constants.GMX.TokenAddress.OP,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/25244/standard/Optimism.png?1696524385",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/optimism"
        },
        new GmxToken
        {
            Name = "Pepe",
            Symbol = "PEPE",
            Address = Constants.GMX.TokenAddress.PEPE,
            Decimals = 18,
            PriceDecimals = 8,
            ImageUrl = "https://assets.coingecko.com/coins/images/29850/standard/pepe-token.jpeg?1696528776",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/pepe"
        },
        new GmxToken
        {
            Name = "dogwifhat",
            Symbol = "WIF",
            Address = Constants.GMX.TokenAddress.WIF,
            Decimals = 6,
            ImageUrl = "https://assets.coingecko.com/coins/images/33566/standard/dogwifhat.jpg?1702499428",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/dogwifhat"
        },
        new GmxToken
        {
            Name = "Shiba Inu",
            Symbol = "SHIB",
            Address = Constants.GMX.TokenAddress.SHIB,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/11939/standard/shiba.png?1696511800",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/shiba-inu",
            IsSynthetic = true,
            PriceDecimals = 8
        },
        new GmxToken
        {
            Name = "APE Coin",
            Symbol = "APE",
            Address = Constants.GMX.TokenAddress.APE,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/11939/standard/shiba.png?1696511800",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/shiba-inu",
            IsSynthetic = true,
            PriceDecimals = 8
        },
        new GmxToken
        {
            Name = "Stacks",
            Symbol = "STX",
            Address = Constants.GMX.TokenAddress.STX,
            Decimals = 6,
            ImageUrl = "https://assets.coingecko.com/coins/images/2069/standard/Stacks_Logo_png.png?1709979332",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/stacks",
            IsSynthetic = true,
        },
        new GmxToken
        {
            Name = "ORDI",
            Symbol = "ORDI",
            Address = Constants.GMX.TokenAddress.ORDI,
            Decimals = 18,
            ImageUrl = "https://assets.coingecko.com/coins/images/30162/standard/ordi.png?1696529082",
            CoingeckoUrl = "https://www.coingecko.com/en/coins/ordi",
            IsSynthetic = true,
        },
    };

    public static GmxToken NATIVE_TOKEN = TOKENS.First(t => t.IsNative);
    public static GmxToken WRAPPRED_NATIVE_TOKEN = TOKENS.First(t => t.IsWrapped);

    public static List<GmxToken> GetTokens()
    {
        return TOKENS;
    }

    public static GmxToken GetTokenByAddress(string address)
    {
        var token = TOKENS.FirstOrDefault(t => GmxV2Helpers.SameAddress(t.Address, address));
        if (token == null)
            throw new Exception($"Token with address '{address}' not found");

        return token;
    }

    public static string ConvertTokenAddress(string address, string convertTo = null)
    {
        if (convertTo == "wrapped" && address == NATIVE_TOKEN.Address)
        {
            return WRAPPRED_NATIVE_TOKEN.Address;
        }

        if (convertTo == "native" && address == WRAPPRED_NATIVE_TOKEN.Address)
        {
            return NATIVE_TOKEN.Address;
        }

        return address;
    }

    public static string GetMarketFullName(string indexToken, string longToken, string shortToken, bool isSpotOnly)
    {
        return $"{GetMarketIndexName(indexToken, isSpotOnly)} [{GetMarketPoolName(longToken, shortToken)}]";
    }


    public static string GetMarketIndexName(string indexToken, bool isSpotOnly)
    {
        if (isSpotOnly)
        {
            return "SPOT-ONLY";
        }

        return indexToken;
    }

    public static string GetMarketPoolName(string longToken, string shortToken)
    {
        if (longToken == shortToken)
        {
            return longToken;
        }

        return $"{longToken}-{shortToken}";
    }

    public static GmxToken GetByTicker(Enums.Ticker ticker)
    {
        return TOKENS.FirstOrDefault(t => t.Symbol == ticker.ToString()) ?? throw new InvalidOperationException();
    }
}

public class GmxToken
{
    public string Name { get; set; }
    public string Symbol { get; set; }
    public int Decimals { get; set; }
    public string Address { get; set; }
    public bool IsNative { get; set; }
    public bool IsShortable { get; set; }
    public string ImageUrl { get; set; }
    public string CoingeckoUrl { get; set; }
    public bool IsV1Available { get; set; }
    public bool IsStable { get; set; }
    public string ExplorerUrl { get; set; }
    public string BaseSymbol { get; set; }
    public string AssetSymbol { get; set; }
    public bool IsWrapped { get; set; }
    public int PriceDecimals { get; set; }
    public bool IsSynthetic { get; set; }
    public bool IsPlatform { get; set; }
}