namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
///
/// Required capability for every driver instance. Owns lifecycle, metadata, health.
/// Other capabilities (, ,
/// , , ,
/// , ,
/// ) are composable — a driver implements only what its
/// backend actually supports.
///
public interface IDriver
{
/// Stable logical ID of this driver instance, sourced from the central config DB.
string DriverInstanceId { get; }
/// Driver type name (e.g. "Galaxy", "Modbus", "AbCip"). Matches DriverInstance.DriverType.
string DriverType { get; }
/// Initialize the driver from its DriverConfig JSON; open connections; prepare for first use.
/// The driver configuration as JSON.
/// Cancellation token for the operation.
/// A task that represents the asynchronous operation.
Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken);
///
/// Apply a config change in place without tearing down the driver process.
/// Invoked by the v2 DriverInstanceActor when ApplyDelta reports that only this
/// driver's config changed in the new deployment.
///
///
/// Per docs/v2/driver-stability.md §"In-process only (Tier A/B)" — Reinitialize is the
/// only Core-initiated recovery path for in-process drivers; if it fails, the driver instance
/// is marked Faulted and its nodes go Bad quality, but the server process keeps running.
///
/// The driver configuration as JSON.
/// Cancellation token for the operation.
/// A task that represents the asynchronous operation.
Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken);
/// Stop the driver, close connections, release resources. Called on shutdown or driver removal.
///
/// Land the terminal health value AFTER the teardown, never only before it (Gitea #517).
/// Teardown drains in-flight poll / probe loops, and those loops write health as they unwind — so a
/// driver that wrote first and then tore down could have a late
/// loop overwrite it with and leave THAT as the resting state,
/// with every connection already closed. This is why the fleet writes last, and it is the reason
/// #517's original suggestion — "write the transitional value before disposing" — is only safe as an
/// ADDITIONAL write, bracketing the teardown, rather than as a move.
/// Bracketing matters wherever a can land mid-teardown. It cannot on
/// this path today: DriverInstanceActor calls this from PostStop, on the actor thread,
/// after the mailbox has drained, so its health poll is serialised against it. It CAN on the
/// initialize path, which the same actor runs on a fire-and-forget Task.Run while the health
/// tick keeps firing — so a driver whose disposes anything on its
/// failure path must write the failed state before disposing as well as after.
///
/// Cancellation token for the operation.
/// A task that represents the asynchronous operation.
Task ShutdownAsync(CancellationToken cancellationToken);
/// Current health snapshot, polled by Core for the status dashboard and ServiceLevel.
/// Must reflect the driver's ACTUAL state rather than a constant — a hard-coded
/// reports a healthy driver after shutdown and before initialize
/// alike, which is what Gitea #517 found in CalculationDriver. A driver with no transport still
/// has a running / not-running distinction worth reporting.
/// The driver's current health snapshot.
DriverHealth GetHealth();
}