using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Serilog;
using ZB.MOM.WW.LmxProxy.Host.Domain;
using ZB.MOM.WW.LmxProxy.Host.Metrics;
using ZB.MOM.WW.LmxProxy.Host.Subscriptions;

namespace ZB.MOM.WW.LmxProxy.Host.Health
{
    /// <summary>
    ///     Basic health check: connection state, success rate, client count.
    /// </summary>
    public class HealthCheckService : IHealthCheck
    {
        private static readonly ILogger Logger = Log.ForContext<HealthCheckService>();

        private readonly IScadaClient _scadaClient;
        private readonly SubscriptionManager _subscriptionManager;
        private readonly PerformanceMetrics _performanceMetrics;

        public HealthCheckService(
            IScadaClient scadaClient,
            SubscriptionManager subscriptionManager,
            PerformanceMetrics performanceMetrics)
        {
            _scadaClient = scadaClient;
            _subscriptionManager = subscriptionManager;
            _performanceMetrics = performanceMetrics;
        }

        public Task<HealthCheckResult> CheckHealthAsync(
            HealthCheckContext context,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var data = new Dictionary<string, object>();

                var isConnected = _scadaClient.IsConnected;
                data["scada_connected"] = isConnected;
                data["scada_connection_state"] = _scadaClient.ConnectionState.ToString();

                var subscriptionStats = _subscriptionManager.GetStats();
                data["subscription_total_clients"] = subscriptionStats.TotalClients;
                data["subscription_total_tags"] = subscriptionStats.TotalTags;

                long totalOperations = 0;
                double totalSuccessRate = 0;
                int operationCount = 0;

                foreach (var kvp in _performanceMetrics.GetAllMetrics())
                {
                    var stats = kvp.Value.GetStatistics();
                    totalOperations += stats.TotalCount;
                    totalSuccessRate += stats.SuccessRate;
                    operationCount++;
                }

                double averageSuccessRate = operationCount > 0
                    ? totalSuccessRate / operationCount
                    : 1.0;

                data["total_operations"] = totalOperations;
                data["average_success_rate"] = averageSuccessRate;

                if (!isConnected)
                {
                    return Task.FromResult(HealthCheckResult.Unhealthy(
                        "SCADA client is not connected", data: data));
                }

                if (averageSuccessRate < 0.5 && totalOperations > 100)
                {
                    return Task.FromResult(HealthCheckResult.Degraded(
                        "Average success rate is below 50%", data: data));
                }

                if (subscriptionStats.TotalClients > 100)
                {
                    return Task.FromResult(HealthCheckResult.Degraded(
                        "High client count: " + subscriptionStats.TotalClients, data: data));
                }

                return Task.FromResult(HealthCheckResult.Healthy(
                    "LmxProxy is healthy", data: data));
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Health check failed");
                return Task.FromResult(HealthCheckResult.Unhealthy(
                    "Health check failed: " + ex.Message, ex));
            }
        }
    }
}
