using ZB.MOM.WW.GalaxyRepository;

namespace ZB.MOM.WW.MxGateway.Server.Sessions;

/// <summary>
///     Rewrites a bare MXAccess attribute address to its writable array form by appending the
///     trailing <c>[]</c> suffix when Galaxy Repository metadata reports the attribute as an array.
///     MXAccess requires the <c>[]</c> suffix on the AddItem address for an array attribute to be
///     writable; the bare name registers a read-only-ish handle. This is best-effort: when metadata
///     is cold, the address is unknown, or the attribute is not an array, the address is returned
///     unchanged and no exception is thrown.
/// </summary>
public sealed class ArrayAddressNormalizer(IGalaxyHierarchyCache cache)
{
    private const string ArraySuffix = "[]";

    /// <summary>
    ///     Returns <paramref name="address"/> with a trailing <c>[]</c> appended when Galaxy metadata
    ///     reports it as an array attribute; otherwise returns it unchanged. Never throws.
    /// </summary>
    /// <param name="address">The MXAccess attribute address to normalize.</param>
    /// <returns>The normalized address, or the original address when no rewrite applies.</returns>
    public string Normalize(string address)
    {
        if (string.IsNullOrWhiteSpace(address))
        {
            return address;
        }

        if (address.EndsWith(ArraySuffix, StringComparison.Ordinal))
        {
            return address;
        }

        // Galaxy SQL keys array attributes by their suffixed FullTagReference (e.g. "Obj.Arr[]"),
        // so probe for the suffixed form to decide whether the bare name is an array.
        string suffixed = address + ArraySuffix;
        return cache.Current.Index.TagsByAddress.TryGetValue(suffixed, out GalaxyTagLookup? lookup)
            && lookup.Attribute?.IsArray == true
                ? suffixed
                : address;
    }
}
