using System.Text.Json;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace Managing.Api.HealthChecks
{
    public class Web3ProxyHealthCheck : IHealthCheck
    {
        private readonly HttpClient _httpClient;
        private readonly string _web3ProxyUrl;

        public Web3ProxyHealthCheck(IHttpClientFactory httpClientFactory, string web3ProxyUrl)
        {
            _httpClient = httpClientFactory.CreateClient("Web3ProxyHealthCheck");
            _web3ProxyUrl = web3ProxyUrl;
        }

        public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
        {
            try
            {
                var response = await _httpClient.GetAsync($"{_web3ProxyUrl}/health", cancellationToken);
                
                if (!response.IsSuccessStatusCode)
                {
                    return HealthCheckResult.Degraded(
                        $"Web3Proxy health check failed with status code: {response.StatusCode}",
                        data: new Dictionary<string, object>
                        {
                            ["StatusCode"] = (int)response.StatusCode,
                            ["Endpoint"] = $"{_web3ProxyUrl}/health"
                        });
                }

                var content = await response.Content.ReadAsStringAsync(cancellationToken);
                
                // Parse the JSON response to extract the detailed data
                using (JsonDocument document = JsonDocument.Parse(content))
                {
                    var root = document.RootElement;
                    string status = "healthy";
                    string message = "Web3Proxy is healthy";
                    
                    if (root.TryGetProperty("status", out var statusElement))
                    {
                        status = statusElement.GetString();
                    }
                    
                    // Extract the detailed data from the Web3Proxy response
                    var data = new Dictionary<string, object>();
                    
                    // Parse timestamp if available
                    if (root.TryGetProperty("timestamp", out var timestampElement))
                    {
                        data["timestamp"] = timestampElement.GetString();
                    }
                    
                    // Parse version if available
                    if (root.TryGetProperty("version", out var versionElement))
                    {
                        data["version"] = versionElement.GetString();
                    }
                    
                    // Parse checks if available
                    if (root.TryGetProperty("checks", out var checksElement))
                    {
                        // Extract Privy check
                        if (checksElement.TryGetProperty("privy", out var privyElement))
                        {
                            var privyData = new Dictionary<string, object>();
                            
                            if (privyElement.TryGetProperty("status", out var privyStatusElement))
                            {
                                privyData["status"] = privyStatusElement.GetString();
                            }
                            
                            if (privyElement.TryGetProperty("message", out var privyMessageElement))
                            {
                                privyData["message"] = privyMessageElement.GetString();
                            }
                            
                            data["privy"] = privyData;
                        }
                        
                        // Extract GMX check
                        if (checksElement.TryGetProperty("gmx", out var gmxElement))
                        {
                            var gmxData = new Dictionary<string, object>();
                            
                            if (gmxElement.TryGetProperty("status", out var gmxStatusElement))
                            {
                                gmxData["status"] = gmxStatusElement.GetString();
                            }
                            
                            if (gmxElement.TryGetProperty("message", out var gmxMessageElement))
                            {
                                gmxData["message"] = gmxMessageElement.GetString();
                            }
                            
                            // Extract GMX market data
                            if (gmxElement.TryGetProperty("data", out var gmxDataElement))
                            {
                                if (gmxDataElement.TryGetProperty("marketCount", out var marketCountElement))
                                {
                                    gmxData["marketCount"] = marketCountElement.GetInt32();
                                }
                                
                                if (gmxDataElement.TryGetProperty("responseTimeMs", out var responseTimeElement))
                                {
                                    gmxData["responseTimeMs"] = responseTimeElement.GetInt32();
                                }
                                
                                if (gmxDataElement.TryGetProperty("uiFeeFactor", out var uiFeeFactorElement))
                                {
                                    gmxData["uiFeeFactor"] = uiFeeFactorElement.GetString();
                                }
                                
                                if (gmxDataElement.TryGetProperty("sampleMarkets", out var sampleMarketsElement))
                                {
                                    var sampleMarkets = new List<Dictionary<string, string>>();
                                    
                                    for (int i = 0; i < sampleMarketsElement.GetArrayLength(); i++)
                                    {
                                        var marketElement = sampleMarketsElement[i];
                                        var market = new Dictionary<string, string>();
                                        
                                        if (marketElement.TryGetProperty("marketAddress", out var addressElement))
                                        {
                                            market["marketAddress"] = addressElement.GetString();
                                        }
                                        
                                        if (marketElement.TryGetProperty("indexToken", out var indexTokenElement))
                                        {
                                            market["indexToken"] = indexTokenElement.GetString();
                                        }
                                        
                                        if (marketElement.TryGetProperty("longToken", out var longTokenElement))
                                        {
                                            market["longToken"] = longTokenElement.GetString();
                                        }
                                        
                                        if (marketElement.TryGetProperty("shortToken", out var shortTokenElement))
                                        {
                                            market["shortToken"] = shortTokenElement.GetString();
                                        }
                                        
                                        sampleMarkets.Add(market);
                                    }
                                    
                                    gmxData["sampleMarkets"] = sampleMarkets;
                                }
                            }
                            
                            data["gmx"] = gmxData;
                        }
                    }
                    
                    // Determine overall health result based on status
                    if (status.ToLower() == "healthy")
                    {
                        return HealthCheckResult.Healthy(
                            "Web3Proxy is healthy",
                            data: data);
                    }
                    else if (status.ToLower() == "degraded")
                    {
                        return HealthCheckResult.Degraded(
                            "Web3Proxy is degraded",
                            data: data);
                    }
                    else
                    {
                        return HealthCheckResult.Unhealthy(
                            "Web3Proxy is unhealthy",
                            data: data);
                    }
                }
            }
            catch (Exception ex)
            {
                return HealthCheckResult.Unhealthy(
                    "Failed to connect to Web3Proxy",
                    ex,
                    data: new Dictionary<string, object>
                    {
                        ["Endpoint"] = $"{_web3ProxyUrl}/health",
                        ["ErrorMessage"] = ex.Message,
                        ["ErrorType"] = ex.GetType().Name
                    });
            }
        }
    }
} 