public interface IPromotionService
{
    /// <summary>
    /// Approves a verified or awaiting-clinical-approval batch and promotes its draft data
    /// into live VigilCareClinical tables within a single atomic transaction.
    /// </summary>
    /// <param name="batchId">The batch to promote.</param>
    /// <param name="approverUserId">The user performing the approval (separation-of-duties enforced).</param>
    /// <param name="enableRetroactiveAlerts">
    /// If true, outbox events are written for backfill observations so the alert engine processes them.
    /// If false (default), backfill observations are silently inserted with no alert path.
    /// Live-capture track always writes outbox events regardless of this flag.
    /// </param>
    /// <param name="idempotencyKey">Optional key for idempotent promotion. If provided and already used, returns cached result.</param>
    /// <returns>The promotion result with all created live IDs.</returns>
    Task<PromotionResultResponse> ApproveAndPromoteAsync(
        Guid batchId, Guid approverUserId, bool enableRetroactiveAlerts, string? idempotencyKey);

    /// <summary>
    /// Returns the promotion result for an already-promoted batch.
    /// </summary>
    Task<PromotionResultResponse> GetPromotionResultAsync(Guid batchId);

    Task<PromotionResult> PromoteAsync(Guid batchId, Guid actorUserId);
}