using GraphQL.Client.Abstractions;
using GraphQL;
using Managing.Core;
using Managing.Infrastructure.Evm.Abstractions;
using Managing.Infrastructure.Evm.Subgraphs.Models;
using Managing.Domain.Candles;
using Managing.Infrastructure.Evm.Extensions;
using static Managing.Common.Enums;

namespace Managing.Infrastructure.Evm.Subgraphs;

public class ChainlinkGmx : ISubgraphPrices
{
    SubgraphProvider ISubgraphPrices.GetProvider() => SubgraphProvider.ChainlinkGmx;

    private readonly IGraphQLClient _graphQLClient;
    private readonly string _baseToken = "_USD";
    private Dictionary<string, string> _feeds = new Dictionary<string, string>()
    {
        {"BTC_USD", "0xae74faa92cb67a95ebcab07358bc222e33a34da7" },
        {"ETH_USD", "0x37bc7498f4ff12c19678ee8fe19d713b87f6a9e6" },
        {"BNB_USD", "0xc45ebd0f901ba6b2b8c7e70b717778f055ef5e6d" },
        {"LINK_USD", "0xdfd03bfc3465107ce570a0397b247f546a42d0fa" },
        {"UNI_USD", "0x68577f915131087199fe48913d8b416b3984fd38" },
        {"SUSHI_USD", "0x7213536a36094cd8a768a5e45203ec286cba2d74" },
        {"AVAX_USD", "0x0fc3657899693648bba4dbd2d8b33b82e875105d" },
        {"AAVE_USD", "0xe3f0dede4b499c07e12475087ab1a084b5f93bc0" },
        {"YFI_USD", "0x8a4d74003870064d41d4f84940550911fbfccf04" },
        {"SPELL_USD", "0x8640b23468815902e011948f3ab173e1e83f9879" },
    };

    public ChainlinkGmx(IGraphQLClient graphQLHttpClient)
    {
        _graphQLClient = graphQLHttpClient ?? throw new ArgumentNullException(nameof(graphQLHttpClient));
    }


    public async Task<IEnumerable<Candle>> GetPrices(Ticker ticker, DateTime startDate, Timeframe timeframe)
    {
        var path = ticker.ToString() + _baseToken;
        var feed = _feeds.GetValueOrDefault(path);
        var perChunk = 1000;
        var totalChunk = 6;
        var priceRounds = new List<Round>();
        var feedCondition = $@"{{ feed: ""{feed}"" }}";

        for (int i = 0; i < totalChunk; i++)
        {
            var query = $"{{ rounds(first: {perChunk}, skip: {i * perChunk}, orderBy: unixTimestamp, orderDirection: desc, where: {feedCondition} ) {{ unixTimestamp,value}} }}";
            var graphQuery = new GraphQLRequest
            {
                Query = query
            };

            var response = await _graphQLClient.SendQueryAsync<PriceRoundsChainlinkGmx>(graphQuery);
            priceRounds.AddRange(response.Data.Rounds);
        }

        var rounds = new List<Round>();
        var uniqTs = new HashSet<int>();

        foreach (var round in priceRounds)
        {
            if (uniqTs.Contains(round.UnixTimestamp))
            {
                continue;
            }

            uniqTs.Add(round.UnixTimestamp);
            rounds.Add(new Round
            {
                UnixTimestamp = round.UnixTimestamp,
                Value = (double.Parse(round.Value) / 1e8).ToString(),
                Date = DateHelpers.GetFromUnixTimestamp(round.UnixTimestamp)
            });
        }

        rounds.Sort((timeA, timeB) => timeA.UnixTimestamp - timeB.UnixTimestamp);

        return rounds.ToArray().GetCandles(timeframe, ticker);
    }

    public Task<decimal> GetVolume(Ticker ticker)
    {
        throw new NotImplementedException();
    }

    public Task<IEnumerable<Ticker>> GetTickers()
    {
        throw new NotImplementedException();
    }
}
