namespace StorageService.Domain.SeedWork;

/// <summary>
/// EN: Base class for Value Objects following DDD patterns.
/// VI: Lớp cơ sở cho Value Objects theo mẫu DDD.
/// </summary>
/// <remarks>
/// EN: Value objects are immutable and compared by their values, not identity.
/// VI: Value objects là bất biến và được so sánh theo giá trị, không phải định danh.
/// </remarks>
public abstract class ValueObject
{
    /// <summary>
    /// EN: Get the atomic values that make up this value object.
    /// VI: Lấy các giá trị nguyên tử tạo nên value object này.
    /// </summary>
    protected abstract IEnumerable<object?> GetEqualityComponents();

    public override bool Equals(object? obj)
    {
        if (obj is null || obj.GetType() != GetType())
            return false;

        var other = (ValueObject)obj;
        return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
    }

    public override int GetHashCode()
    {
        return GetEqualityComponents()
            .Select(x => x?.GetHashCode() ?? 0)
            .Aggregate((x, y) => x ^ y);
    }

    public static bool operator ==(ValueObject? left, ValueObject? right)
    {
        return left?.Equals(right) ?? right is null;
    }

    public static bool operator !=(ValueObject? left, ValueObject? right)
    {
        return !(left == right);
    }

    /// <summary>
    /// EN: Create a copy of this value object with modifications.
    /// VI: Tạo bản sao của value object này với các thay đổi.
    /// </summary>
    protected ValueObject GetCopy()
    {
        return (ValueObject)MemberwiseClone();
    }
}
