package de.effigenix.shared.common;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Currency;
import java.util.Objects;

/**
 * Value Object representing a monetary amount with currency.
 * Immutable and self-validating.
 */
public record Money(BigDecimal amount, Currency currency) {

    public Money {
        Objects.requireNonNull(amount, "Amount must not be null");
        Objects.requireNonNull(currency, "Currency must not be null");
        if (amount.scale() > 2) {
            throw new IllegalArgumentException("Amount scale must not exceed 2 decimal places");
        }
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Amount must not be negative");
        }
    }

    public static Money euro(BigDecimal amount) {
        return new Money(amount.setScale(2, RoundingMode.HALF_UP), Currency.getInstance("EUR"));
    }

    public static Result<String, Money> tryEuro(BigDecimal amount) {
        try {
            return Result.success(euro(amount));
        } catch (IllegalArgumentException e) {
            return Result.failure(e.getMessage());
        }
    }

    public static Money zero() {
        return new Money(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP), Currency.getInstance("EUR"));
    }

    public Money add(Money other) {
        if (!this.currency.equals(other.currency)) {
            throw new IllegalArgumentException("Cannot add Money with different currencies");
        }
        return new Money(this.amount.add(other.amount), this.currency);
    }

    public Money multiply(BigDecimal factor) {
        return new Money(
                this.amount.multiply(factor).setScale(2, RoundingMode.HALF_UP),
                this.currency
        );
    }
}
