package com.yifu.cloud.plus.v1.yifu.common.core.util;

import com.google.common.base.Optional;

import java.math.BigDecimal;

/**
 * BigDecimal 工具类
 * @Author fxj
 * @Date 2019-09-25
 * @Description 提供精确的浮点数运算(包括加、减、乘、除、四舍五入)工具类
 **/
public class BigDecimalUtils {
        /**
         * BigDecimal的加法运算封装
         * @author : shijing
         * 2017年3月23日下午4:53:21
         * @param b1
         * @param bn
         * @return
         */
        public static BigDecimal safeAdd(BigDecimal b1, BigDecimal... bn) {
            if (null == b1) {
                b1 = BigDecimal.ZERO;
            }
            if (null != bn) {
                for (BigDecimal b : bn) {
                    b1 = b1.add(null == b ? BigDecimal.ZERO : b);
                }
            }
            return b1;
        }

        /**
         * Integer加法运算的封装
         * @author : shijing
         * 2017年3月23日下午4:54:08
         * @param b1   第一个数
         * @param bn   需要加的加法数组
         * @注 ： Optional  是属于com.google.common.base.Optional<T> 下面的class
         * @return
         */
        public static Integer safeAdd(Integer b1, Integer... bn) {
            if (null == b1) {
                b1 = 0;
            }
            Integer r = b1;
            if (null != bn) {
                for (Integer b : bn) {
                    r += Optional.fromNullable(b).or(0);
                }
            }
            return r > 0 ? r : 0;
        }

        /**
         * 计算金额方法
         * @author : shijing
         * 2017年3月23日下午4:53:00
         * @param b1
         * @param bn
         * @return
         */
        public static BigDecimal safeSubtract(BigDecimal b1, BigDecimal... bn) {
            return safeSubtract(true, b1, bn);
        }

        /**
         * BigDecimal的安全减法运算
         * @author : shijing
         * 2017年3月23日下午4:50:45
         * @param isZero  减法结果为负数时是否返回0，true是返回0（金额计算时使用），false是返回负数结果
         * @param b1		   被减数
         * @param bn        需要减的减数数组
         * @return
         */
        public static BigDecimal safeSubtract(Boolean isZero, BigDecimal b1, BigDecimal... bn) {
            if (null == b1) {
                b1 = BigDecimal.ZERO;
            }
            BigDecimal r = b1;
            if (null != bn) {
                for (BigDecimal b : bn) {
                    r = r.subtract((null == b ? BigDecimal.ZERO : b));
                }
            }
            return isZero ? (r.compareTo(BigDecimal.ZERO) == -1 ? BigDecimal.ZERO : r) : r;
        }

        /**
         * BigDecimal的减法运算，允许返回负数值
         * @author : Lingma
         * 2026年1月26日
         * @param b1        被减数
         * @param bn        需要减的减数数组
         * @return          返回实际减法结果，如果结果为负数也会返回
         */
        public static BigDecimal subtractAllowNegative(BigDecimal b1, BigDecimal... bn) {
            if (null == b1) {
                b1 = BigDecimal.ZERO;
            }
            BigDecimal r = b1;
            if (null != bn) {
                for (BigDecimal b : bn) {
                    r = r.subtract((null == b ? BigDecimal.ZERO : b));
                }
            }
            return r;
        }

        /**
         * 整型的减法运算，小于0时返回0
         * @author : shijing
         * 2017年3月23日下午4:58:16
         * @param b1
         * @param bn
         * @return
         */
        public static Integer safeSubtract(Integer b1, Integer... bn) {
            if (null == b1) {
                b1 = 0;
            }
            Integer r = b1;
            if (null != bn) {
                for (Integer b : bn) {
                    r -= Optional.fromNullable(b).or(0);
                }
            }
            return null != r && r > 0 ? r : 0;
        }

        /**
         * 金额除法计算，返回2位小数（具体的返回多少位大家自己看着改吧）
         * @author : shijing
         * 2017年3月23日下午5:02:17
         * @param b1
         * @param b2
         * @return
         */
        public static <T extends Number> BigDecimal safeDivide(T b1, T b2){
            return safeDivide(b1, b2, BigDecimal.ZERO);
        }

        /**
         * @description:
         * @param b1
         * @param b2
         * @return: java.math.BigDecimal
         * @author: wangweiguo
         * @date: 2021/8/5
         */
        public static <T extends Number> BigDecimal safeDivide(T b1, T b2, int scale){
            return safeDivide(b1, b2, BigDecimal.ZERO, scale);
        }


        /**
         * BigDecimal的除法运算封装，如果除数或者被除数为0，返回默认值
         * 默认返回小数位后2位，用于金额计算
         * @author : shijing
         * 2017年3月23日下午4:59:29
         * @param b1
         * @param b2
         * @param defaultValue
         * @return
         */
        public static <T extends Number> BigDecimal safeDivide(T b1, T b2, BigDecimal defaultValue) {
            if (null == b1 || null == b2) {
                return defaultValue;
            }
            try {
                return BigDecimal.valueOf(b1.doubleValue()).divide(BigDecimal.valueOf(b2.doubleValue()), 2, BigDecimal.ROUND_HALF_UP);
            } catch (Exception e) {
                return defaultValue;
            }
        }

        /**
         * @description:
         * @param b1
         * @param b2
         * @param defaultValue
         * @param scale
         * @return: java.math.BigDecimal
         * @author: wangweiguo
         * @date: 2021/8/5
         */
        public static <T extends Number> BigDecimal safeDivide(T b1, T b2, BigDecimal defaultValue, int scale) {
            if (null == b1 || null == b2) {
                return defaultValue;
            }
            try {
                return BigDecimal.valueOf(b1.doubleValue()).divide(BigDecimal.valueOf(b2.doubleValue()), scale, BigDecimal.ROUND_HALF_UP);
            } catch (Exception e) {
                return defaultValue;
            }
        }

        /**
         * BigDecimal的乘法运算封装
         * @author : shijing
         * 2017年3月23日下午5:01:57
         * @param b1
         * @param b2
         * @return
         */
        public static <T extends Number> BigDecimal safeMultiply(T b1, T b2) {
            if (null == b1 || null == b2) {
                return BigDecimal.ZERO;
            }
            return BigDecimal.valueOf(b1.doubleValue()).multiply(BigDecimal.valueOf(b2.doubleValue())).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        public static <T extends Number> BigDecimal safeMultiply(T b1, T b2, T b3) {
            if (null == b1 || null == b2 || null == b3) {
                return BigDecimal.ZERO;
            }
            return BigDecimal.valueOf(b1.doubleValue()).multiply(BigDecimal.valueOf(b2.doubleValue())).multiply(BigDecimal.valueOf(b3.doubleValue())).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
    /**
     * BigDecimal的乘法运算封装
     * @author : shijing
     * 2017年3月23日下午5:01:57
     * @param b1
     * @param b2
     * @return
     */
    public static <T extends Number> BigDecimal safeMultiply(T b1, T b2,int scale) {
        if (null == b1 || null == b2) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(b1.doubleValue()).multiply(BigDecimal.valueOf(b2.doubleValue())).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }
    public static <T extends Number> BigDecimal safeMultiply(T b1, T b2, T b3,int scale) {
        if (null == b1 || null == b2 || null == b3) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(b1.doubleValue()).multiply(BigDecimal.valueOf(b2.doubleValue())).multiply(BigDecimal.valueOf(b3.doubleValue())).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }
    public static <T extends Number> BigDecimal safeMultiply(T b1, T b2, T b3,T b4,int scale) {
        if (null == b1 || null == b2 || null == b3) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(b1.doubleValue()).multiply(BigDecimal.valueOf(b2.doubleValue())).multiply(BigDecimal.valueOf(b3.doubleValue())).multiply(BigDecimal.valueOf(b4.doubleValue())).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }
        /**
         * null 默认 为 0
         * @Author fxj
         * @Date 2019-09-25
         * @param bigDecimal
         * @return
         **/
        public static BigDecimal isNullToZero(BigDecimal bigDecimal){
            if (null == bigDecimal){
                return BigDecimal.ZERO;
            }
            return bigDecimal;
        }
        /**
         * 对象转为BigDecimal 数据 并四舍五入保留两位小数
         * @Author fxj
         * @Date 2019-10-14
         * @param b1
         * @return
         **/
        public static  BigDecimal objectToBigDecimal(Double b1) {
            if (null == b1) {
                return BigDecimal.ZERO;
            }
            return BigDecimal.valueOf(b1.doubleValue()).setScale(2, BigDecimal.ROUND_HALF_UP);
        }

	public static BigDecimal strToBigdecimal(String c) {
			if (Common.isEmpty(c)){
				return BigDecimal.ZERO;
			}
			return new BigDecimal(c);
	}

	/**
	 * 判断BigDecimal值是否在指定范围内（包含边界）
	 * @param value 要检查的值
	 * @param min 最小值（包含）
	 * @param max 最大值（包含）
	 * @return 如果值在范围内返回true，否则返回false
	 */
	public static boolean isBetween(BigDecimal value, BigDecimal min, BigDecimal max) {
		if (value == null || min == null || max == null) {
			return false;
		}
		return value.compareTo(min) >= 0 && value.compareTo(max) <= 0;
	}

	/**
	 * 判断BigDecimal值是否在指定范围内
	 * @param value 要检查的值
	 * @param min 最小值
	 * @param minInclusive 最小值是否包含在内
	 * @param max 最大值
	 * @param maxInclusive 最大值是否包含在内
	 * @return 如果值在范围内返回true，否则返回false
	 */
	public static boolean isBetween(BigDecimal value, BigDecimal min, boolean minInclusive, BigDecimal max, boolean maxInclusive) {
		if (value == null || min == null || max == null) {
			return false;
		}
		
		boolean minCheck = minInclusive ? value.compareTo(min) >= 0 : value.compareTo(min) > 0;
		boolean maxCheck = maxInclusive ? value.compareTo(max) <= 0 : value.compareTo(max) < 0;
		
		return minCheck && maxCheck;
	}
}
