using Microsoft.Extensions.Logging;
using ZB.MOM.WW.ScadaBridge.Commons.Types;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;

namespace ZB.MOM.WW.ScadaBridge.Transport.Serialization;

/// <summary>
/// Import-time normalization of attribute values to the native-typed JSON form.
/// <para>
/// Bundles exported before the native-typed-JSON change carry List attribute
/// values in the old quoted-element form (e.g. <c>["10","20"]</c> for an
/// <see cref="DataType.Int32"/> list). Already-exported bundle files can't be
/// rewritten, so List values are normalised on import: every DTO→entity write
/// site routes the value through <see cref="NormalizeListValue"/> so imported
/// data lands native (<c>[10,20]</c>). The central DB normalizer remains the
/// backstop for anything that slips through.
/// </para>
/// <para>
/// Non-List attributes and null/empty values pass through unchanged. A value
/// that fails to decode (malformed JSON / un-parseable element) is left exactly
/// as-is so the import still succeeds — the DB normalizer is the backstop.
/// </para>
/// </summary>
internal static class ImportValueNormalizer
{
    /// <summary>
    /// Returns the native-typed JSON form of a List attribute value, or the
    /// value unchanged for non-List / null / empty / malformed inputs.
    /// </summary>
    /// <param name="value">The attribute value as carried by the bundle DTO.</param>
    /// <param name="dataType">The attribute's declared data type.</param>
    /// <param name="elementType">The List element type (null for scalars).</param>
    /// <param name="logger">Optional logger; a warning is emitted when a malformed value is left as-is.</param>
    /// <param name="attributeName">Optional attribute name for the diagnostic message.</param>
    /// <returns>The native-typed JSON form of the value, or the value unchanged when not applicable.</returns>
    public static string? NormalizeListValue(
        string? value,
        DataType dataType,
        DataType? elementType,
        ILogger? logger = null,
        string? attributeName = null)
    {
        if (dataType != DataType.List || string.IsNullOrEmpty(value))
        {
            return value;
        }

        try
        {
            return AttributeValueCodec.Encode(
                AttributeValueCodec.Decode(value, DataType.List, elementType));
        }
        catch (FormatException ex)
        {
            // Leave malformed values exactly as imported; the DB normalizer is
            // the backstop. Never abort the import for a single bad value.
            logger?.LogWarning(ex,
                "Bundle import: could not normalize List value for attribute {Attribute}; " +
                "importing verbatim (the central DB normalizer is the backstop).",
                attributeName ?? "(unknown)");
            return value;
        }
    }
}
