using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace CMSMicroservice.Application.HealthCQ.Queries.GetSystemHealth;

public class GetSystemHealthQueryHandler : IRequestHandler<GetSystemHealthQuery, GetSystemHealthResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly IConfiguration _configuration;

    public GetSystemHealthQueryHandler(IApplicationDbContext context, IConfiguration configuration)
    {
        _context = context;
        _configuration = configuration;
    }

    public async Task<GetSystemHealthResponseDto> Handle(GetSystemHealthQuery request, CancellationToken cancellationToken)
    {
        var services = new List<ServiceHealthDto>();
        var overallHealthy = true;

        // Database Health Check
        var dbHealth = await CheckDatabaseHealth(cancellationToken);
        services.Add(dbHealth);
        if (dbHealth.Status != HealthStatusDto.Healthy) overallHealthy = false;

        // Memory Health Check
        var memoryHealth = CheckMemoryHealth();
        services.Add(memoryHealth);
        if (memoryHealth.Status != HealthStatusDto.Healthy) overallHealthy = false;

        // External Services Health (if any)
        // TODO: Add external service health checks

        return new GetSystemHealthResponseDto
        {
            OverallHealthy = overallHealthy,
            Services = services,
            CheckedAt = DateTime.UtcNow,
            Version = GetApplicationVersion(),
            Environment = _configuration["Environment"] ?? "Unknown"
        };
    }

    private async Task<ServiceHealthDto> CheckDatabaseHealth(CancellationToken cancellationToken)
    {
        var startTime = DateTime.UtcNow;
        try
        {
            // Simple database connectivity check
            var canConnect = await _context.Users.AnyAsync(cancellationToken);
            var responseTime = (DateTime.UtcNow - startTime).TotalMilliseconds;

            return new ServiceHealthDto
            {
                ServiceName = "Database",
                Status = HealthStatusDto.Healthy,
                Description = "Database connection is healthy",
                ResponseTimeMs = (long)responseTime,
                LastCheck = DateTime.UtcNow,
                Details = new List<HealthDetailDto>
                {
                    new() { Key = "ConnectionString", Value = "Connected", Status = HealthStatusDto.Healthy },
                    new() { Key = "ResponseTime", Value = $"{responseTime:F2}ms", Status = responseTime < 1000 ? HealthStatusDto.Healthy : HealthStatusDto.Degraded }
                }
            };
        }
        catch (Exception ex)
        {
            var responseTime = (DateTime.UtcNow - startTime).TotalMilliseconds;
            return new ServiceHealthDto
            {
                ServiceName = "Database",
                Status = HealthStatusDto.Unhealthy,
                Description = $"Database connection failed: {ex.Message}",
                ResponseTimeMs = (long)responseTime,
                LastCheck = DateTime.UtcNow,
                Details = new List<HealthDetailDto>
                {
                    new() { Key = "Error", Value = ex.Message, Status = HealthStatusDto.Unhealthy }
                }
            };
        }
    }

    private ServiceHealthDto CheckMemoryHealth()
    {
        var process = System.Diagnostics.Process.GetCurrentProcess();
        var workingSetMB = process.WorkingSet64 / 1024 / 1024;
        var status = workingSetMB < 500 ? HealthStatusDto.Healthy : 
                    workingSetMB < 1000 ? HealthStatusDto.Degraded : HealthStatusDto.Unhealthy;

        return new ServiceHealthDto
        {
            ServiceName = "Memory",
            Status = status,
            Description = $"Current memory usage: {workingSetMB}MB",
            ResponseTimeMs = 0,
            LastCheck = DateTime.UtcNow,
            Details = new List<HealthDetailDto>
            {
                new() { Key = "WorkingSet", Value = $"{workingSetMB}MB", Status = status },
                new() { Key = "ProcessName", Value = process.ProcessName, Status = HealthStatusDto.Healthy }
            }
        };
    }

    private string GetApplicationVersion()
    {
        return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown";
    }
}