namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;

/// <summary>
/// Central → site relay command: gracefully fail over the owning site's two-node cluster.
/// Sent over the command/control channel when an Administrator clicks "Trigger failover" on a
/// site card in the Central UI Health dashboard.
/// </summary>
/// <remarks>
/// <para>
/// Central and each site are SEPARATE Akka clusters, so central cannot act on a site's
/// membership directly — it can only ask. The site's own <c>SiteCommunicationActor</c> performs
/// the <c>Cluster.Leave</c> against its site-specific <c>site-{SiteId}</c> role, which is the
/// role its singletons (the Deployment Manager) are scoped to.
/// </para>
/// <para>
/// Either site node may receive this: <c>SiteCommunicationActor</c> is registered per node
/// (not as a singleton), and central's gRPC dial reaches whichever node answers. That is
/// fine — <c>Cluster.Leave(address)</c> is valid from any member, and the target is resolved
/// from cluster state rather than from who received the message.
/// </para>
/// <para>
/// <b>Rolling upgrade:</b> a site running a binary older than this contract has no handler for
/// this message; it becomes an unhandled message / dead letter and central's Ask times out.
/// The timeout is reported to the operator as "site did not respond", which is the correct
/// user-facing outcome — an old site genuinely cannot honour the request. Message evolution
/// stays additive-only.
/// </para>
/// </remarks>
/// <param name="CorrelationId">Correlation id echoed on the ack.</param>
/// <param name="SiteId">The site whose pair should fail over. Carried explicitly so a
/// misrouted command is detectable at the site rather than silently acted on.</param>
public sealed record TriggerSiteFailover(
    string CorrelationId,
    string SiteId);

/// <summary>
/// Site → central ack for a <see cref="TriggerSiteFailover"/> relay command.
/// </summary>
/// <param name="CorrelationId">Correlation id of the originating relay command.</param>
/// <param name="Accepted">
/// <c>true</c> when the site resolved a target and issued the graceful Leave.
/// <c>false</c> is a definitive refusal from the site — most often the peer guard (fewer than
/// two Up members in the site role, so a failover would be an outage) or a site-id mismatch.
/// A <c>false</c> ack is NOT a transport failure and must be distinguished from an
/// unreachable-site timeout.
/// </param>
/// <param name="TargetAddress">Address of the node that is leaving; <c>null</c> when refused.</param>
/// <param name="ErrorMessage">Reason for a refusal, or a fault message; <c>null</c> on success.</param>
public sealed record SiteFailoverAck(
    string CorrelationId,
    bool Accepted,
    string? TargetAddress,
    string? ErrorMessage);
