namespace Domain.Entities.Common.ValueObject
{
    public sealed record Money
    {
        public decimal Value { get; }
        public string Currency { get; }

        private Money(decimal value, string currency)
        {
            if (value < 0)
            {
                throw new ArgumentException("금액은 음수가 될 수 없습니다.");
            }

            Currency = currency;
            Value = Normalize(value, currency);
        }

        public static Money KRW(decimal value) => new(value, "KRW");

        public static Money Zero(string currency) => new(0m, currency);

        public bool IsZero => Value == 0m;

        public static Money operator +(Money a, Money b)
        {
            EnsureSameCurrency(a, b);

            return new Money(a.Value + b.Value, a.Currency);
        }

        public static Money operator -(Money a, Money b)
        {
            EnsureSameCurrency(a, b);

            if (a.Value < b.Value)
            {
                throw new InvalidOperationException("잔액 부족");
            }

            return new Money(a.Value - b.Value, a.Currency);
        }

        public static bool operator >=(Money a, Money b)
        {
            EnsureSameCurrency(a, b);

            return a.Value >= b.Value;
        }

        public static bool operator <=(Money a, Money b)
        {
            EnsureSameCurrency(a, b);

            return a.Value <= b.Value;
        }

        private static void EnsureSameCurrency(Money a, Money b)
        {
            if (a.Currency != b.Currency)
            {
                throw new InvalidOperationException("통화가 다릅니다.");
            }
        }

        private static decimal Normalize(decimal value, string currency)
        {
            var scale = currency == "KRW" ? 0 : 2; // KRW 0자리, 그 외 2자리 같은 정책 예시

            return decimal.Round(value, scale, MidpointRounding.AwayFromZero);
        }
    }
}