using Akka.Actor;
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
using ZB.MOM.WW.ScadaBridge.Host.Actors;

namespace ZB.MOM.WW.ScadaBridge.Host;

/// <summary>
/// Sends SiteHealthReport to the local SiteCommunicationActor via Akka ActorSelection,
/// which forwards it to central. The send is an acked round-trip (review 01 [Medium]):
/// it Asks and awaits the central <see cref="SiteHealthReportAck"/>, so a lost or
/// rejected report faults the sender's task (driving its counter-restore path).
/// </summary>
public class AkkaHealthReportTransport : IHealthReportTransport
{
    private readonly AkkaHostedService _akkaService;

    private static readonly TimeSpan AckTimeout = TimeSpan.FromSeconds(10);

    /// <summary>
    /// Initializes a new <see cref="AkkaHealthReportTransport"/> backed by the given Akka hosted service.
    /// </summary>
    /// <param name="akkaService">The Akka hosted service used to access the running actor system.</param>
    public AkkaHealthReportTransport(AkkaHostedService akkaService)
    {
        _akkaService = akkaService;
    }

    /// <inheritdoc />
    public async Task SendAsync(SiteHealthReport report, CancellationToken cancellationToken)
    {
        var actorSystem = _akkaService.ActorSystem
            ?? throw new InvalidOperationException("Actor system not started — health report not sent");

        var siteComm = actorSystem.ActorSelection("/user/site-communication");
        var ack = await siteComm.Ask<SiteHealthReportAck>(report, AckTimeout, cancellationToken)
            .ConfigureAwait(false);
        if (!ack.Accepted)
            throw new InvalidOperationException($"Health report #{report.SequenceNumber} rejected: {ack.Error}");
    }
}
