package cn.iocoder.foodnexus.framework.common.util.number;

import cn.hutool.core.math.Money;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.foodnexus.framework.common.util.CommonUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 金额工具类
 *
 * @author 芋道源码
 */
public class MoneyUtils {

    /**
     * 金额的小数位数
     */
    private static final int PRICE_SCALE = 2;

    /**
     * 百分比对应的 BigDecimal 对象
     */
    public static final BigDecimal PERCENT_100 = BigDecimal.valueOf(100);

    /**
     * 计算百分比金额，四舍五入
     *
     * @param price 金额
     * @param rate  百分比，例如说 56.77% 则传入 56.77
     * @return 百分比金额
     */
    public static Integer calculateRatePrice(Integer price, Double rate) {
        return calculateRatePrice(price, rate, 0, RoundingMode.HALF_UP).intValue();
    }

    /**
     * 计算百分比金额，向下传入
     *
     * @param price 金额
     * @param rate  百分比，例如说 56.77% 则传入 56.77
     * @return 百分比金额
     */
    public static Integer calculateRatePriceFloor(Integer price, Double rate) {
        return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue();
    }

    /**
     * 计算百分比金额
     *
     * @param price   金额（单位分）
     * @param count   数量
     * @param percent 折扣（单位分），列如 60.2%，则传入 6020
     * @return 商品总价
     */
    public static Integer calculator(Integer price, Integer count, Integer percent) {
        price = price * count;
        if (percent == null) {
            return price;
        }
        return MoneyUtils.calculateRatePriceFloor(price, (double) (percent / 100));
    }

    /**
     * 计算百分比金额（BigDecimal 数量）
     *
     * @param price   金额（单位分）
     * @param count   数量（BigDecimal）
     * @param percent 折扣（单位分），列如 60.2%，则传入 6020
     * @return 商品总价
     */
    public static Integer calculator(Integer price, BigDecimal count, Integer percent) {
        int totalPrice = BigDecimal.valueOf(price).multiply(count)
                .setScale(0, RoundingMode.DOWN).intValue();
        if (percent == null) {
            return totalPrice;
        }
        return MoneyUtils.calculateRatePriceFloor(totalPrice, (double) (percent / 100));
    }

    /**
     * 计算百分比金额
     *
     * @param price        金额
     * @param rate         百分比，例如说 56.77% 则传入 56.77
     * @param scale        保留小数位数
     * @param roundingMode 舍入模式
     */
    public static BigDecimal calculateRatePrice(Number price, Number rate, int scale, RoundingMode roundingMode) {
        return NumberUtil.toBigDecimal(price).multiply(NumberUtil.toBigDecimal(rate)) // 乘以
                .divide(BigDecimal.valueOf(100), scale, roundingMode); // 除以 100
    }

    /**
     * 分转元
     *
     * @param fen 分
     * @return 元
     */
    public static BigDecimal fenToYuan(Integer fen) {
        try {
            if (CommonUtil.isEmpty(fen)) {
                return null;
            }
            return new Money(0, fen).getAmount();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 分转元（字符串）
     *
     * 例如说 fen 为 1 时，则结果为 0.01
     *
     * @param fen 分
     * @return 元
     */
    public static String fenToYuanStr(Integer fen) {
        try {
            if (CommonUtil.isEmpty(fen)) {
                return null;
            }
            return new Money(0, fen).toString();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 金额相乘，默认进行四舍五入
     *
     * 位数：{@link #PRICE_SCALE}
     *
     * @param price 金额
     * @param count 数量
     * @return 金额相乘结果
     */
    public static BigDecimal priceMultiply(BigDecimal price, BigDecimal count) {
        if (price == null || count == null) {
            return null;
        }
        return price.multiply(count).setScale(PRICE_SCALE, RoundingMode.HALF_UP);
    }

    /**
     * 金额相乘（百分比），默认进行四舍五入
     *
     * 位数：{@link #PRICE_SCALE}
     *
     * @param price  金额
     * @param percent 百分比
     * @return 金额相乘结果
     */
    public static BigDecimal priceMultiplyPercent(BigDecimal price, BigDecimal percent) {
        if (price == null || percent == null) {
            return null;
        }
        return price.multiply(percent).divide(PERCENT_100, PRICE_SCALE, RoundingMode.HALF_UP);
    }

    /**
     * BigDecimal与int相乘，向下截断后转为int
     * @param decimal 待相乘的BigDecimal（如金额、费率）
     * @param integer 待相乘的int（如数量、倍数）
     * @return 向下截断后的int结果
     * @throws ArithmeticException 结果超出int范围时抛出
     */
    public static Integer multiplyAndRoundToInt(BigDecimal decimal, Integer integer) {
        if (decimal == null) {
            throw new IllegalArgumentException("BigDecimal参数不能为空");
        }
        BigDecimal resultBigDecimal = decimal.multiply(BigDecimal.valueOf(integer))
                .setScale(0, RoundingMode.DOWN);
        return resultBigDecimal.intValueExact();
    }

    /**
     * 价格（int）与数量（BigDecimal）相乘，向下截断后转为int
     * <p>用于单位为分的价格计算，结果出现小数时只保留整数部分，不四舍五入</p>
     *
     * @param price 单价（单位：分）
     * @param count 数量（BigDecimal）
     * @return 向下截断后的int总价
     */
    public static Integer priceMultiplyCount(Integer price, BigDecimal count) {
        if (price == null || count == null) {
            return null;
        }
        return BigDecimal.valueOf(price).multiply(count)
                .setScale(0, RoundingMode.DOWN).intValue();
    }

}
