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

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;

/// <summary>
/// Client-side TagConfig validation dispatched by <c>DriverType</c> (parallel to
/// <see cref="TagConfigEditorMap"/>). Each entry parses the tag's config JSON into the driver's typed
/// model and runs its <c>Validate()</c>. Returns an error string to block the TagModal save, or null
/// when the config is valid — or when no typed validator is registered (unmapped drivers use the raw
/// textarea and are validated server-side at deploy). Keys are the canonical
/// <see cref="DriverTypeNames"/> constants (case-insensitive) so this map can never drift.
/// </summary>
public static class TagConfigValidator
{
    private static readonly IReadOnlyDictionary<string, Func<string?, string?>> Validators =
        new Dictionary<string, Func<string?, string?>>(StringComparer.OrdinalIgnoreCase)
        {
            [DriverTypeNames.Modbus]      = j => ModbusTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.S7]          = j => S7TagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.AbCip]       = j => AbCipTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.AbLegacy]    = j => AbLegacyTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.TwinCAT]     = j => TwinCATTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.FOCAS]       = j => FocasTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.OpcUaClient] = j => OpcUaClientTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.Calculation] = j => CalculationTagConfigModel.FromJson(j).Validate(),
            // Keyed off SqlDriver.DriverTypeName (= "Sql") — see the note in TagConfigEditorMap.
            [SqlDriver.DriverTypeName]     = j => SqlTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.Mqtt]        = j => MqttTagConfigModel.FromJson(j).Validate(),
            [DriverTypeNames.MTConnect]   = j => MTConnectTagConfigModel.FromJson(j).Validate(),
        };

    /// <summary>
    /// Validates a tag's <paramref name="configJson"/> for the given <paramref name="driverType"/>.
    /// Returns an error string to block save, or null when valid / no typed validator is registered.
    /// </summary>
    /// <param name="driverType">The driver type name to look up a typed validator for.</param>
    /// <param name="configJson">The tag's config JSON to validate.</param>
    /// <returns>An error string to block save, or null when the config is valid or unmapped.</returns>
    public static string? Validate(string? driverType, string? configJson)
        => driverType is not null && Validators.TryGetValue(driverType, out var v) ? v(configJson) : null;
}
