using System.Text.Json;
using TradingBot.Models;

namespace TradingBot.Services;

public class CoinGeckoMarketDataService : IMarketDataService
{
    private readonly HttpClient _httpClient;
    private readonly Dictionary<string, string> _symbolToId = new()
    {
        { "BTC", "bitcoin" },
        { "ETH", "ethereum" },
        { "BNB", "binancecoin" },
        { "XRP", "ripple" },
        { "ADA", "cardano" },
        { "SOL", "solana" },
        { "DOT", "polkadot" }
    };

    public CoinGeckoMarketDataService(HttpClient httpClient)
    {
        _httpClient = httpClient;
        _httpClient.BaseAddress = new Uri("https://api.coingecko.com/api/v3/");
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "NovaTrader-Bot");
    }

    public async Task<List<MarketPrice>> GetMarketPricesAsync(List<string> symbols)
    {
        var prices = new List<MarketPrice>();
        
        // Convert symbols to CoinGecko IDs
        var ids = string.Join(",", symbols.Select(s => _symbolToId.GetValueOrDefault(s.ToUpper(), s.ToLower())));
        
        try
        {
            // CoinGecko API: /simple/price endpoint
            var response = await _httpClient.GetAsync(
                $"simple/price?ids={ids}&vs_currencies=usd&include_24hr_vol=true&include_24hr_change=true&include_last_updated_at=true");
            
            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync();
                var data = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);
                
                if (data != null)
                {
                    foreach (var symbol in symbols)
                    {
                        var coinId = _symbolToId.GetValueOrDefault(symbol.ToUpper(), symbol.ToLower());
                        if (data.TryGetValue(coinId, out var coinData))
                        {
                            var price = new MarketPrice
                            {
                                Symbol = symbol.ToUpper(),
                                Price = coinData.GetProperty("usd").GetDecimal(),
                                Timestamp = DateTime.UtcNow
                            };

                            // Safely get optional properties
                            if (coinData.TryGetProperty("usd_24h_change", out var changeElement))
                            {
                                price.Change24h = changeElement.GetDecimal();
                            }

                            if (coinData.TryGetProperty("usd_24h_vol", out var volumeElement))
                            {
                                price.Volume24h = volumeElement.GetDecimal();
                            }

                            prices.Add(price);
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine($"CoinGecko API error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}");
            }
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"Network error fetching market data: {ex.Message}");
        }
        catch (JsonException ex)
        {
            Console.WriteLine($"JSON parsing error: {ex.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Unexpected error fetching market data: {ex.Message}");
        }
        
        return prices;
    }

    public async Task<MarketPrice?> GetPriceAsync(string symbol)
    {
        var prices = await GetMarketPricesAsync(new List<string> { symbol });
        return prices.FirstOrDefault();
    }
}
