namespace ZB.MOM.WW.ScadaBridge.DeploymentManager;

/// <summary>
/// Configuration options for the central-side Deployment Manager.
/// </summary>
public class DeploymentManagerOptions
{
    /// <summary>
    /// Timeout for a lifecycle command round-trip (disable, enable, delete).
    /// Applied as a linked-CTS deadline in <c>DeploymentService</c> so a hung or
    /// unreachable site does not hold the per-instance operation lock indefinitely.
    /// </summary>
    public TimeSpan LifecycleCommandTimeout { get; set; } = TimeSpan.FromSeconds(30);

    /// <summary>Timeout per site for system-wide artifact deployment.</summary>
    public TimeSpan ArtifactDeploymentTimeoutPerSite { get; set; } = TimeSpan.FromSeconds(120);

    /// <summary>Timeout for acquiring an operation lock on an instance.</summary>
    public TimeSpan OperationLockTimeout { get; set; } = TimeSpan.FromSeconds(5);

    /// <summary>
    /// Maximum number of instance deployments whose SITE ROUND-TRIP runs
    /// concurrently during a bulk <c>DeploySiteAsync</c>. The flatten/validate and
    /// persistence phases stay serial regardless (they share one non-thread-safe
    /// <c>DbContext</c>); only the network wait is fanned out.
    ///
    /// <para>
    /// Bounded rather than unbounded so a large site cannot open one in-flight
    /// gRPC command per instance against a two-node site pair. Four mirrors the
    /// conservative end of the site's own apply concurrency; raise it only with
    /// evidence from the target-scale load test.
    /// </para>
    /// </summary>
    public int SiteDeploymentMaxParallelism { get; set; } = 4;

    /// <summary>
    /// Per-instance deadline applied to the site round-trip inside a bulk
    /// <c>DeploySiteAsync</c>. One unreachable or wedged instance is recorded as a
    /// failed row and the rest of the batch continues — the bulk operation never
    /// inherits a single instance's hang.
    /// </summary>
    public TimeSpan SiteDeploymentTimeoutPerInstance { get; set; } = TimeSpan.FromSeconds(120);

    /// <summary>
    /// Retention window for TERMINAL deployment records (<c>Success</c>,
    /// <c>Failed</c>). Deployments are insert-only — one row per attempt, forever —
    /// so without a window the table grows without bound and every unfiltered
    /// deployment query gets slower with the age of the system.
    ///
    /// <para>
    /// Deliberately generous (one year) because deployment history is
    /// operator-facing forensics, and deliberately terminal-only: an
    /// <c>InProgress</c> or <c>Pending</c> row is never purged regardless of age,
    /// because it is exactly the row the query-before-redeploy reconciliation
    /// path needs to find. Set to <see cref="TimeSpan.Zero"/> to disable purging.
    /// </para>
    /// </summary>
    public TimeSpan TerminalDeploymentRecordRetention { get; set; } = TimeSpan.FromDays(365);
}
