using System.Text.RegularExpressions;
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer;
///
/// Options for the SQL Server historian backend (the ServerHistorian:SqlServer config block).
///
public sealed partial class SqlServerHistorianOptions
{
/// Required. ADO.NET connection string for the historian database (never the ConfigDb).
public string ConnectionString { get; set; } = "";
/// SQL schema holding the historian objects. Spliced into DDL/DML, so it is regex-validated.
public string Schema { get; set; } = "hist";
/// Per-command timeout. Must be positive.
public TimeSpan CommandTimeout { get; set; } = TimeSpan.FromSeconds(30);
///
/// true creates the schema and applies missing scripts on first use; false only verifies
/// that the required schema version (SqlServerSchemaBootstrapper.RequiredVersion, currently 2) exists and
/// fails every historian call with a clear error otherwise.
///
public bool AutoCreateSchema { get; set; } = true;
///
/// Days of history to keep, measured on source time. null (default) keeps everything. When set,
/// a driver node deletes older hist.Sample/hist.Event rows every .
///
public int? RetentionDays { get; set; }
/// How often the retention purge runs. Must be positive.
public TimeSpan PurgeInterval { get; set; } = TimeSpan.FromHours(1);
///
/// Rows per DELETE TOP(n) batch. Default 4000 stays under SQL Server's 5000-lock escalation
/// threshold so a purge never escalates to a table lock.
///
public int PurgeBatchSize { get; set; } = 4000;
[GeneratedRegex("^[A-Za-z_][A-Za-z0-9_]{0,127}$")]
private static partial Regex IdentifierRegex();
/// True when is a safe SQL identifier.
/// Candidate schema name.
/// Whether it matches ^[A-Za-z_][A-Za-z0-9_]{0,127}$.
public static bool IsValidSchemaName(string? schema) => schema is not null && IdentifierRegex().IsMatch(schema);
/// Validates the options without touching SQL.
/// One message per problem; empty when valid.
public IReadOnlyList Validate()
{
var errors = new List();
if (string.IsNullOrWhiteSpace(ConnectionString))
errors.Add("ServerHistorian:SqlServer:ConnectionString is required.");
if (!IsValidSchemaName(Schema))
errors.Add("ServerHistorian:SqlServer:Schema must be a SQL identifier matching ^[A-Za-z_][A-Za-z0-9_]{0,127}$.");
if (CommandTimeout <= TimeSpan.Zero)
errors.Add("ServerHistorian:SqlServer:CommandTimeout must be greater than zero.");
if (RetentionDays is < 1)
errors.Add("ServerHistorian:SqlServer:RetentionDays must be at least 1 when set (omit it to keep history forever).");
if (PurgeInterval <= TimeSpan.Zero)
errors.Add("ServerHistorian:SqlServer:PurgeInterval must be greater than zero.");
if (PurgeBatchSize < 1)
errors.Add("ServerHistorian:SqlServer:PurgeBatchSize must be at least 1.");
return errors;
}
}