namespace ZB.MOM.WW.ScadaBridge.CentralUI.Services;

/// <summary>
/// Admin-triggered manual failover of the central pair. Declared here — and in terms of
/// plain strings — so CentralUI stays Akka-free; the Akka implementation lives in the Host
/// (<c>AkkaManualFailoverService</c>) and is registered only in the Central branch.
/// </summary>
public interface IManualFailoverService
{
    /// <summary>
    /// Gracefully fails over the central cluster: the current active (oldest Up) member
    /// leaves, restarts via its supervisor, and rejoins as standby. The Leave is graceful,
    /// never a Down, so cluster singletons hand over instead of being killed.
    /// <para>
    /// The caller is usually connected THROUGH the node being failed over (Traefik routes
    /// the UI to the active node), so the calling Blazor circuit should expect to drop and
    /// reconnect against the new active node.
    /// </para>
    /// </summary>
    /// <param name="actor">Authenticated user name, recorded on the audit row.</param>
    /// <returns>The address acted on, or <c>null</c> when there is no peer to fail over to
    /// (failing over a lone node would be an outage, not a failover).</returns>
    Task<string?> FailOverCentralAsync(string actor);

    /// <summary>
    /// Asks a SITE to gracefully fail over its own two-node pair. Central and each site are
    /// separate Akka clusters, so this is a request relayed over the command/control channel —
    /// the site performs the Leave itself and reports the outcome. Unlike central failover,
    /// this does NOT disturb the caller's own UI session.
    /// </summary>
    /// <param name="siteId">The site whose pair should fail over.</param>
    /// <param name="actor">Authenticated user name, recorded on the audit row.</param>
    /// <returns>The site's outcome — accepted with a target, or refused with a reason.</returns>
    Task<SiteFailoverOutcome> FailOverSiteAsync(string siteId, string actor);
}

/// <summary>
/// Outcome of a site-pair failover request, in UI terms. Deliberately distinct from the wire
/// ack so CentralUI stays free of the Akka message contract.
/// </summary>
/// <param name="Accepted"><c>true</c> when the site issued the graceful Leave.</param>
/// <param name="TargetAddress">Address of the leaving site node; <c>null</c> when refused.</param>
/// <param name="ErrorMessage">
/// Why the request was refused or failed. A refusal (peer guard, misroute) is a definitive
/// answer FROM the site; an unreachable site surfaces here as a timeout message. Both are
/// reported to the operator rather than being flattened into a generic failure.
/// </param>
public sealed record SiteFailoverOutcome(bool Accepted, string? TargetAddress, string? ErrorMessage);
