namespace adas_core.Domain.Utils;

public sealed class EquatableDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>, IEquatable<ComparableDictionary<TKey, TValue>>
    where TKey : notnull where TValue : notnull
{
    /// <summary>
    /// Determines whether the current dictionary is equal to another <see cref="ComparableDictionary{TKey, TValue}"/> by comparing their counts and key-value pairs.
    /// Returns <c>false</c> if the other dictionary is <c>null</c>, has a different count, is missing any key present in this dictionary, or contains a different value for any shared key.
    /// </summary>
    /// <param name="other">The dictionary to compare against this instance.</param>
    /// <returns><c>true</c> if both dictionaries contain the same keys with equal values; otherwise, <c>false</c>.</returns>
    public bool Equals(ComparableDictionary<TKey, TValue>? other)
        {
            if (other is null) return false;
            if (Count != other.Count) return false;
            foreach (var pair in this)
            {
                if (!other.TryGetValue(pair.Key, out var otherValue)) return false;
                if (!EqualityComparer<TValue>.Default.Equals(pair.Value, otherValue)) return false;
            }
    
            return true;
        }
    //private readonly Dictionary<TKey, TValue> dictionary = new();

    /// <summary>
    /// Determines whether the current instance is equal to the specified object by attempting to cast it to a <see cref="ComparableDictionary{TKey, TValue}"/> and delegating to the typed equality comparison. Returns <c>false</c> when the supplied object is not a <see cref="ComparableDictionary{TKey, TValue}"/>.
    /// </summary>
    /// <param name="other">The object to compare with the current instance.</param>
    /// <returns><c>true</c> if <paramref name="other"/> is a <see cref="ComparableDictionary{TKey, TValue}"/> and is equal to the current instance; otherwise, <c>false</c>.</returns>
    public override bool Equals(object? other)
        {
            return Equals(other as ComparableDictionary<TKey, TValue>);
        }

    /// <summary>
    /// Computes a hash code for the collection by combining the hash codes of each key-value pair.
    /// Each pair contributes a hash derived from its key and value, and the per-pair hashes are combined using XOR.
    /// </summary>
    /// <returns>An integer hash code that represents the contents of the collection.</returns>
    public override int GetHashCode()
        {
            var hash = 0;
            foreach (var pair in this)
            {
                var miniHash = 17;
                miniHash = miniHash * 31 +
                           EqualityComparer<TKey>.Default.GetHashCode(pair.Key);
                miniHash = miniHash * 31 +
                           EqualityComparer<TValue>.Default.GetHashCode(pair.Value);
                hash ^= miniHash;
            }
    
            return hash;
        }

    // Implementation of IDictionary<,> which just delegates to the dictionary
}