using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.Overview.Registry;

namespace ZB.MOM.WW.Overview.Observability;

/// <summary>
/// Reports how much registry the dashboard actually bound, and fails if it bound none.
/// </summary>
/// <remarks>
/// The pre-host <c>ConfigPreflight</c> and the options validator already refuse to start on an
/// empty registry, so the unhealthy branch is a backstop rather than an expected state. The check
/// earns its place on the reported counts: an operator looking at <c>/health/ready</c> after a
/// config change can see how many instances this process is watching without reading its
/// configuration files.
/// </remarks>
public sealed class RegistryLoadedHealthCheck : IHealthCheck
{
    private readonly OverviewOptions _options;

    /// <summary>Initializes a new <see cref="RegistryLoadedHealthCheck"/>.</summary>
    /// <param name="options">The bound registry.</param>
    public RegistryLoadedHealthCheck(IOptions<OverviewOptions> options)
    {
        ArgumentNullException.ThrowIfNull(options);
        _options = options.Value;
    }

    /// <inheritdoc/>
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        var applications = _options.Applications.Count;
        var instances = _options.Applications.Sum(a => a.Instances.Count);

        var data = new Dictionary<string, object>(StringComparer.Ordinal)
        {
            ["applications"] = applications,
            ["instances"] = instances,
        };

        return Task.FromResult(instances > 0
            ? HealthCheckResult.Healthy(
                $"Watching {instances} instance(s) across {applications} application(s).",
                data)
            : HealthCheckResult.Unhealthy(
                "The registry contains no instances; the dashboard has nothing to watch.",
                exception: null,
                data));
    }
}
