using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using StellaOps.Scanner.Queue.Nats;
using StellaOps.Scanner.Queue.Redis;

namespace StellaOps.Scanner.Queue;

public sealed class ScannerQueueHealthCheck : IHealthCheck
{
    private readonly IScanQueue _queue;
    private readonly ILogger<ScannerQueueHealthCheck> _logger;

    public ScannerQueueHealthCheck(
        IScanQueue queue,
        ILogger<ScannerQueueHealthCheck> logger)
    {
        _queue = queue ?? throw new ArgumentNullException(nameof(queue));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        try
        {
            switch (_queue)
            {
                case RedisScanQueue redisQueue:
                    await redisQueue.PingAsync(cancellationToken).ConfigureAwait(false);
                    return HealthCheckResult.Healthy("Redis queue reachable.");

                case NatsScanQueue natsQueue:
                    await natsQueue.PingAsync(cancellationToken).ConfigureAwait(false);
                    return HealthCheckResult.Healthy("NATS queue reachable.");

                default:
                    return HealthCheckResult.Healthy("Queue transport without dedicated ping returned healthy.");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Scanner queue health check failed.");
            return new HealthCheckResult(
                context.Registration.FailureStatus,
                "Queue transport unreachable.",
                ex);
        }
    }
}
