using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using ZB.MOM.WW.Auth.ApiKeys.Sqlite;

namespace ZB.MOM.WW.MxGateway.Server.Diagnostics;

/// <summary>
/// Readiness probe: verifies the SQLite authentication store is reachable. The gateway
/// authenticates every gRPC call against this store, so its reachability gates readiness.
/// </summary>
public sealed class AuthStoreHealthCheck : IHealthCheck
{
    private readonly AuthSqliteConnectionFactory _connectionFactory;

    /// <summary>Initializes a new instance of the <see cref="AuthStoreHealthCheck"/> class.</summary>
    /// <param name="connectionFactory">Factory used to open connections to the SQLite auth store.</param>
    public AuthStoreHealthCheck(AuthSqliteConnectionFactory connectionFactory) =>
        _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));

    /// <summary>Verifies the SQLite auth store is reachable by executing a trivial query.</summary>
    /// <param name="context">The health check context.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>Healthy when the store responds; otherwise Unhealthy with the underlying exception.</returns>
    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            await using SqliteConnection connection =
                await _connectionFactory.OpenConnectionAsync(cancellationToken).ConfigureAwait(false);
            await using SqliteCommand command = connection.CreateCommand();
            command.CommandText = "SELECT 1;";
            await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
            return HealthCheckResult.Healthy("Auth store is reachable.");
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            throw;
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy("Auth store is unreachable.", ex);
        }
    }
}
