using Microsoft.Extensions.Diagnostics.HealthChecks;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;

namespace ZB.MOM.WW.ScadaBridge.Host.Health;

/// <summary>
/// /health/active check for a SITE pair: Healthy only on the pair's primary — the oldest Up member
/// carrying the <c>site-{SiteId}</c> role. Same active/standby semantics central publishes, so a
/// consumer reads one contract fleet-wide (200 = Active, 503 = Standby).
/// </summary>
/// <remarks>
/// Deliberately NOT central's unscoped shared <c>ActiveNodeHealthCheck</c>: that one calls
/// <c>ClusterActivityEvaluator.SelfIsOldest(cluster)</c> with no role argument, so on a mesh that
/// carries more than one site's members it computes "oldest" across the wrong member set and a site
/// node could report Active because it happens to be the oldest member overall. Delegating to
/// <see cref="IClusterNodeProvider.SelfIsPrimary"/> reuses the role-scoped evaluation the site
/// already trusts for singleton placement and event-log purge — one primary definition per site,
/// not two that can disagree.
/// </remarks>
public sealed class SitePairActiveNodeHealthCheck : IHealthCheck
{
    private readonly IClusterNodeProvider _nodeProvider;

    /// <summary>Initializes a new <see cref="SitePairActiveNodeHealthCheck"/>.</summary>
    /// <param name="nodeProvider">The role-scoped site cluster node provider.</param>
    public SitePairActiveNodeHealthCheck(IClusterNodeProvider nodeProvider) =>
        _nodeProvider = nodeProvider ?? throw new ArgumentNullException(nameof(nodeProvider));

    /// <summary>Reports Healthy on the site pair's primary and Unhealthy on the standby.</summary>
    /// <param name="context">The health check context (unused; the verdict depends only on cluster membership).</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>Healthy on the primary; Unhealthy (503 = Standby) otherwise.</returns>
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default) =>
        Task.FromResult(_nodeProvider.SelfIsPrimary
            ? HealthCheckResult.Healthy("site pair primary (oldest Up member of the site role)")
            : HealthCheckResult.Unhealthy("not the site pair primary (standby)"));
}
