using ZB.MOM.WW.OtOpcUa.Core.Abstractions;

namespace ZB.MOM.WW.OtOpcUa.Driver.Sql.Contracts;

/// <summary>
///     The <c>DriverConfig</c> blob shape for a <c>Sql</c> driver instance (design §5.1). Deserialised by the
///     driver factory, which applies the documented defaults for every absent (null) field and maps the result
///     onto the driver's typed options.
///     <para><b>No connection string lives here.</b> Only <see cref="ConnectionStringRef"/> — a name resolved at
///     Initialize from the environment / secret store (e.g. <c>Sql__ConnectionStrings__MesStaging</c>) — so a
///     deployed artifact never carries database credentials.</para>
///     <para>Enum-valued fields are enum-typed (not strings) so a <c>JsonStringEnumConverter</c> round-trips
///     their <em>names</em> rather than their ordinals. The converter is applied by the factory's
///     <c>JsonSerializerOptions</c> (Task 9), not by an attribute on this DTO — mirroring the driver
///     enum-serialization trap that bit the AdminUI driver pages.</para>
/// </summary>
public sealed class SqlDriverConfigDto
{
    /// <summary>Which ADO.NET provider/dialect backs this instance. Defaults to <see cref="SqlProvider.SqlServer"/> — the only provider v1 constructs.</summary>
    public SqlProvider Provider { get; init; } = SqlProvider.SqlServer;

    /// <summary>
    ///     Name of the connection string to resolve from the environment / secret store at Initialize —
    ///     <b>never</b> the connection string itself.
    /// </summary>
    public string? ConnectionStringRef { get; init; }

    /// <summary>Poll interval applied to groups that do not carry their own. Absent ⇒ the factory default.</summary>
    public TimeSpan? DefaultPollInterval { get; init; }

    /// <summary>
    ///     Per-query wall-clock deadline enforced client-side (a breach surfaces <c>BadTimeout</c>). Must be
    ///     greater than <see cref="CommandTimeout"/>, which is only the server-side backstop (design §8.3).
    /// </summary>
    public TimeSpan? OperationTimeout { get; init; }

    /// <summary>ADO.NET <c>CommandTimeout</c> backstop (seconds granularity server-side).</summary>
    public TimeSpan? CommandTimeout { get; init; }

    /// <summary>Cap on concurrently executing group queries — the connection-pool guard.</summary>
    public int? MaxConcurrentGroups { get; init; }

    /// <summary>When <see langword="true"/>, a NULL cell publishes Bad rather than the default Uncertain.</summary>
    public bool? NullIsBad { get; init; }

    /// <summary>
    ///     Master write kill-switch. <b>v1 is read-only and this field is inert</b> — the driver does not
    ///     implement <c>IWritable</c>, so no value here can produce a write. The factory <em>warns</em> when it
    ///     is authored <see langword="true"/> rather than failing the driver, since the flag cannot do harm but
    ///     an operator who believes writes are enabled can.
    /// </summary>
    public bool? AllowWrites { get; init; }

    /// <summary>
    ///     The authored raw tags the deploy artifact delivers for this driver instance — RawPath identity plus
    ///     the driver <c>TagConfig</c> blob, the same shape every other driver receives. The factory copies
    ///     these onto the driver's options and the driver maps each through
    ///     <see cref="SqlEquipmentTagParser.TryParse"/> at Initialize.
    ///     <para>A SQL source has no tag-discovery protocol, so this list is the complete set of tags the
    ///     instance serves — an absent or empty list is a driver with nothing to poll, not a driver that will
    ///     find its tags later.</para>
    /// </summary>
    public List<RawTagEntry>? RawTags { get; init; }
}
