using MongoDB.Bson;

namespace adas_core.Domain.Utils;

/// <summary>
/// Provides static utility methods for working with BSON (Binary JSON) data.
/// </summary>
public static class BsonUtils
{
    /// <summary>
    /// Converts a <see cref="BsonValue"/> to a corresponding common language runtime (CLR) scalar object, supporting <see cref="int"/>, <see cref="long"/>, <see cref="double"/>, <see cref="DateTime"/> (normalized to UTC), and <see cref="string"/> values.
    /// </summary>
    /// <param name="val">The <see cref="BsonValue"/> instance to convert to a CLR object.</param>
    /// <returns>The underlying CLR value when <paramref name="val"/> is an Int32, Int64, Double, valid DateTime (in UTC), or String; otherwise <see langword="null"/>.</returns>
    public static object? ToObject(this BsonValue val)
        {
            if (val.IsInt32) return val.AsInt32;
    
            if (val.IsInt64) return val.AsInt64;
    
            if (val.IsDouble) return val.AsDouble;
    
            if (val.IsValidDateTime) return val.ToUniversalTime();
    
            if (val.IsString) return val.AsString;
    
            return null;
        }

    /// <summary>
    /// Gets the value associated with the specified key from the BSON document, returning <c>null</c> if the key is not found.
    /// </summary>
    /// <param name="doc">The BSON document to search for the key.</param>
    /// <param name="key">The key of the value to retrieve.</param>
    /// <returns>The <see cref="BsonValue"/> associated with <paramref name="key"/>, or <c>null</c> if the key does not exist.</returns>
    public static BsonValue? Get(this BsonDocument doc, string key)
        {
            return doc.TryGetValue(key, out var value) ? value : null;
        }
}