package yem.base.common.utils;

import java.math.BigDecimal;

/**
 * BigDecimal工具类
 *
 * @author longh
 * @description:
 * @date 2022年5月16日 下午3:39:08
 */
public class BigDecimalUtils {

    public static BigDecimal zero = BigDecimal.ZERO;
    public static BigDecimal one = BigDecimal.ONE;
    public static BigDecimal ten = BigDecimal.TEN;
    public static BigDecimal one_handred = new BigDecimal("100");
    public static BigDecimal one_handred_ten = new BigDecimal("110");
    public static BigDecimal one_thousand = new BigDecimal("1000");
    public static BigDecimal ten_thousand = new BigDecimal("10000");
    public static BigDecimal one_million = new BigDecimal("1000000");

    /***
     * 金额格式转换
     * @param obj
     * @return
     */
    public static BigDecimal toBigDecimal(Object obj) {
        if (obj == null)
            return BigDecimalUtils.zero;
        if (obj instanceof BigDecimal)
            return (BigDecimal) obj;
        if (obj instanceof Integer)
            return new BigDecimal(((Integer) obj).toString());
        if (obj instanceof Long)
            return new BigDecimal(((Long) obj).toString());
        if (obj instanceof Double)
            return new BigDecimal(((Double) obj).doubleValue());
        if (obj.toString() == null)
            return BigDecimalUtils.zero;
        String str = obj.toString().trim();
        if (str.toLowerCase().indexOf("e") > -1)
            try {
                return new BigDecimal(str);
            } catch (NumberFormatException e) {
                return BigDecimalUtils.zero;
            }
        if (str.matches("^[+-]?\\d+[\\.\\d]?\\d*+$"))
            return new BigDecimal(str);
        else
            return BigDecimalUtils.zero;
    }

    /***
     * 除
     * @param  a
     * @param  b
     * @param scale 精度
     * @return 金额
     */
    public static BigDecimal div(Object a, Object b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);
        if (bVal.compareTo(zero) == 0)
            return zero;

        return aVal.divide(bVal, scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * 除
     * @param a
     * @param b
     * @param scale 精度
     * @return 金额
     */
    public static BigDecimal div(BigDecimal a, BigDecimal b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);
        if (bVal.compareTo(zero) == 0)
            return zero;

        return aVal.divide(bVal, scale, BigDecimal.ROUND_HALF_UP);

    }

    /**
     * 乘
     *
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal multiply(Object a, Object b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);

        return aVal.multiply(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 乘
     *
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal multiply(BigDecimal a, BigDecimal b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);

        return aVal.multiply(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);

    }

    /**
     * 加
     *
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal add(Object a, Object b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);

        return aVal.add(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * 加
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal add(BigDecimal a, BigDecimal b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);

        return aVal.add(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * 减
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal sub(Object a, Object b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);

        return aVal.subtract(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * 减
     * @param a
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal sub(BigDecimal a, BigDecimal b, int scale) {
        BigDecimal aVal = toBigDecimal(a);
        BigDecimal bVal = toBigDecimal(b);

        return aVal.subtract(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);

    }

    /**
     * 加1
     *
     * @param a
     * @param scale
     * @return
     */
    public static BigDecimal addOne(Object a, int scale) {
        return add(a, one, scale);
    }

    /**
     * 减1
     *
     * @param a
     * @param scale
     * @return
     */
    public static BigDecimal subOne(Object a, int scale) {
        return sub(a, one, scale);
    }

    /**
     * 金额转大写
     *
     * @param n
     * @return
     */
    public static String digitCapital(double n) {
        String fraction[] = {"角", "分"};
        String digit[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String unit[][] = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};

        String head = n < 0 ? "负" : "";
        // 如果是负数取绝对值
        n = Math.abs(n);
        String s = "";
        BigDecimal bigDecimal = new BigDecimal(Double.valueOf(n).toString());
        String nStr = bigDecimal.toString();
        // 小数部分
        String[] split = nStr.split("\\.");
        if (split.length > 1) {
            // 小数点为特殊符号，在分割时需进行转义
            String decimalStr = split[1];
            if (decimalStr.length() > 2) {
                decimalStr = decimalStr.substring(0, 2);
            }
            // 将小数部分转换为整数
            Integer integer = Integer.valueOf(decimalStr);
            String p = "";
            for (int i = 0; i < decimalStr.length() && i < fraction.length; i++) {
                p = digit[integer % 10] + fraction[decimalStr.length() - i - 1] + p;
                integer = integer / 10;
            }
            s = p.replaceAll("(零.)+", "") + s;
        }
        if (s.length() < 1) {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);
        // 整数部分
        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }

    /**
     * 向上取整
     *
     * @param aVal
     * @param scale
     * @return
     */
    public static BigDecimal ceil(double aVal, int scale) {
        aVal = Math.ceil(aVal);
        BigDecimal aVal1 = BigDecimal.valueOf(aVal);
        return aVal1.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 向下取整
     *
     * @param aVal
     * @param scale
     * @return
     */
    public static BigDecimal floor(double aVal, int scale) {
        aVal = Math.floor(aVal);
        BigDecimal aVal1 = BigDecimal.valueOf(aVal);
        return aVal1.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }
}
