using System.Numerics;
using Managing.Common;
using Managing.Domain.Trades;
using Managing.Infrastructure.Evm.Models.Gmx.v1;
using Managing.Infrastructure.Evm.Referentials;
using Managing.Infrastructure.Evm.Services;
using Managing.Infrastructure.Evm.Services.Gmx;
using Nethereum.Web3;
using Xunit;

namespace Managing.Infrastructure.Tests;

public class GmxServiceTests : EvmManagerTests
{
    [Fact]
    public async void Should_return_indexes_from_gmx()
    {
        var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
        var web3 = new Web3(chain.RpcUrl);
        var indexes = await GmxService.GetLastIndex(web3, "");

        Assert.IsType<GmxOrderIndexes>(indexes);
    }

    [Theory]
    [InlineData("")]
    public async void Should_return_gmx_orders(string publicAddress)
    {
        var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
        var web3 = new Web3(chain.RpcUrl);
        var orders = await GmxService.GetOrders(web3, publicAddress, Enums.Ticker.BTC);

        Assert.IsType<List<GmxOrder>>(orders);
    }

    [Fact]
    public async void Should_return_orders()
    {
        var account = PrivateKeys.GetAccount();

        var orders = await _manager.GetOrders(account, Enums.Ticker.BTC);

        Assert.IsType<List<Trade>>(orders);
    }

    [Fact]
    public async void Should_cancel_gmx_orders()
    {
        var account = PrivateKeys.GetAccount();

        var cancelled = await _manager.CancelOrders(account, Enums.Ticker.BTC);

        Assert.IsType<bool>(cancelled);
    }

    [Fact]
    public void Should_convert_quantity()
    {
        var quantity = Web3.Convert.ToWei(0.0019);

        Assert.IsType<BigInteger>(quantity);
    }

    [Fact]
    public async void Should_approve_order()
    {
        var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
        var account = PrivateKeys.GetAccount();
        var web3 = new Web3(chain.RpcUrl);
        var approval = await GmxService.ApproveOrder(web3, Enums.Ticker.BTC, account.Key, 0.0003m);

        Assert.IsType<bool>(approval);
    }

    [Fact]
    public async void Should_check_approved_gmx_plugin()
    {
        var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
        var web3 = new Web3(chain.RpcUrl);
        var isPluginAdded = await GmxService.IsPluginAdded(web3, "", Arbitrum.Address.OrderBook);

        Assert.IsType<bool>(isPluginAdded);
        Assert.True(isPluginAdded);
    }

    [Fact]
    public void Should_return_correct_acceptable_price()
    {
        var acceptablePrice = GmxHelpers.GetAcceptablePrice(16672.76m, true);
        var price = new BigInteger(1662274172);
        var expected = Web3.Convert.ToWei(price, 25);

        Assert.NotNull(acceptablePrice);
        Assert.IsType<BigInteger>(acceptablePrice);
        Assert.Equal(expected, acceptablePrice);
    }

    [Fact]
    public async void Should_return_quantity_in_position()
    {
        var account = PrivateKeys.GetAccount();
        var quantity = await _manager.QuantityInPosition(Constants.Chains.Arbitrum, account, Enums.Ticker.BTC);

        Assert.NotNull(quantity);
    }

    [Fact]
    public async void Should_return_Gmx_position()
    {
        var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
        var web3 = new Web3(chain.RpcUrl);
        var position = await GmxService.GetGmxPosition(web3, "", Enums.Ticker.BTC);

        Assert.IsType<GmxPosition>(position);
    }

    [Fact]
    public async void Should_return_Trade()
    {
        var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
        var web3 = new Web3(chain.RpcUrl);
        var position = await GmxService.GetTrade(web3, "", Enums.Ticker.ETH);

        Assert.IsType<Trade>(position);
    }
}