using Microsoft.EntityFrameworkCore;
using ZB.MOM.WW.OtOpcUa.Configuration;
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;

namespace ZB.MOM.WW.OtOpcUa.Admin.Services;

/// <summary>
///     Read-side service for ClusterNode rows + their cluster-scoped redundancy view. Consumed
///     by the RedundancyTab on the cluster detail page. Writes (role swap, node enable/disable)
///     are not supported here — role swap happens through the RedundancyCoordinator apply-lease
///     flow on the server side and would conflict with any direct DB mutation from Admin.
/// </summary>
public sealed class ClusterNodeService(OtOpcUaConfigDbContext db)
{
    /// <summary>Stale-threshold matching <c>HostStatusService.StaleThreshold</c> — 30s of clock
    /// tolerance covers a missed heartbeat plus publisher GC pauses.</summary>
    public static readonly TimeSpan StaleThreshold = TimeSpan.FromSeconds(30);

    public Task<List<ClusterNode>> ListByClusterAsync(string clusterId, CancellationToken ct) =>
        db.ClusterNodes.AsNoTracking()
            .Where(n => n.ClusterId == clusterId)
            .OrderByDescending(n => n.ServiceLevelBase)
            .ThenBy(n => n.NodeId)
            .ToListAsync(ct);

    public static bool IsStale(ClusterNode node) =>
        node.LastSeenAt is null || DateTime.UtcNow - node.LastSeenAt.Value > StaleThreshold;
}
