using System.ComponentModel.DataAnnotations;
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client;
///
/// Connection options for WonderwareHistorianClient.
///
///
///
/// Retry / backoff ownership (finding 006): this module performs exactly one
/// in-place transport reconnect inside FrameChannel.InvokeAsync with no delay,
/// and does NOT implement exponential reconnect backoff. Broader retry/backoff is the
/// caller's responsibility — the alarm drain worker
/// (Core.AlarmHistorian.SqliteStoreAndForwardSink) and the read-side
/// history router are expected to layer their own backoff on top.
///
///
/// Sidecar TCP host (DNS name or IP) the client dials.
/// Sidecar TCP port (matches the sidecar's OTOPCUA_HISTORIAN_TCP_PORT). Valid range: 1–65535.
/// Per-process shared secret the sidecar will verify in the Hello frame.
/// Diagnostic peer identifier sent in Hello — typically the OtOpcUa instance id.
/// Cap on the TCP connect + Hello round trip on each (re)connect.
/// Cap on a single read/write call once connected.
public sealed record WonderwareHistorianClientOptions(
string Host,
[Range(1, 65535)] int Port,
string SharedSecret,
string PeerName = "OtOpcUa",
TimeSpan? ConnectTimeout = null,
TimeSpan? CallTimeout = null)
{
/// Gets the effective connect timeout, using the default if not explicitly set.
public TimeSpan EffectiveConnectTimeout => ConnectTimeout ?? TimeSpan.FromSeconds(10);
/// Gets the effective call timeout, using the default if not explicitly set.
public TimeSpan EffectiveCallTimeout => CallTimeout ?? TimeSpan.FromSeconds(30);
///
/// Timeout for the AdminUI Test Connect probe, in seconds. The AdminUI clamps to a
/// 60s server-side maximum; this default is what the form pre-fills for new instances.
///
[Display(Name = "Probe timeout (seconds)", Description = "Connection test timeout. Default 15s.", GroupName = "Diagnostics")]
[Range(1, 60)]
public int ProbeTimeoutSeconds { get; init; } = 15;
/// When true, the client wraps the TCP stream in TLS before the Hello handshake.
public bool UseTls { get; init; }
///
/// Optional SHA-1 thumbprint (40 hex characters, no spaces, case-insensitive) the client
/// pins the sidecar's TLS server cert against. When null/empty and
/// is true, the client validates the cert chain normally
/// (CA-issued cert).
///
///
/// The consumer matches against X509Certificate.GetCertHashString() (SHA-1, 40
/// hex chars). Supplying a SHA-256 thumbprint (64 hex chars, the format shown by modern
/// tooling such as certutil or Windows Certificate Manager) will never match and
/// will cause the TLS handshake to fail silently. Only 40-character SHA-1 hex strings
/// are accepted.
///
public string? ServerCertThumbprint { get; init; }
///
///
/// Redacts so the value cannot appear in log output when the
/// options object is passed to a structured-logging statement.
///
public override string ToString() =>
$"WonderwareHistorianClientOptions {{ Host={Host}, Port={Port}, PeerName={PeerName}, UseTls={UseTls}, ServerCertThumbprint={ServerCertThumbprint ?? ""} }}";
}