package com.yc.ship.module.resource.helper;


import com.yc.ship.module.resource.helper.entity.NumberUnitEntity;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author y
 * @date 2025-05-14
 */
public class MathHelper {

    private static BigDecimal MATH_WAN_LEVLE = new BigDecimal("10000");

    private static BigDecimal MATH_YI_LEVLE = new BigDecimal("100000000");


    /**
     * 描述：通过一个整数i获取你所要的哪几个(从0开始) i为 多个2的n次方之和，如i=7，那么根据原值是2的n次方之各，你的原值必定是1，2，4 。
     *
     * @param i 数值
     * @return
     */
    public static int[] getWhich(long i) {
        int exp = Math.getExponent(i);
        if (i == (1 << (exp + 1)) - 1) {
            exp = exp + 1;
        }
        int[] num = new int[exp];
        int x = exp - 1;
        for (int n = 0; (1 << n) < i + 1; n++) {
            if ((1 << (n + 1)) > i && (1 << n) < (i + 1)) {
                num[x] = n;
                i -= 1 << n;
                n = 0;
                x--;
            }
        }
        return num;
    }

    /**
     * 描述：非四舍五入取整处理
     *
     * @param v 需要四舍五入的数字
     * @return
     */
    public static int roundDown(double v) {
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, 0, BigDecimal.ROUND_DOWN).intValue();
    }

    /**
     * 描述：四舍五入取整处理
     *
     * @param v 需要四舍五入的数字
     * @return
     */
    public static int roundUp(double v) {
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, 0, BigDecimal.ROUND_UP).intValue();
    }

    /**
     * 描述：提供精确的小数位四舍五入处理。
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }

        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 描述：四舍五入保留两位小数
     *
     * @param num 数字
     * @return 保留两位小数的数字字串
     */
    public static String format(double num) {
        return format(num, "0.00");
    }

    /**
     * 描述：四舍五入数字保留小数位
     *
     * @param num    数字
     * @param digits 小数位
     * @return
     */
    public static String format(double num, int digits) {
        String pattern = "0";
        if (digits > 0) {
            pattern += "." + createStr("0", digits, "");
        }
        return format(num, pattern);
    }

    /**
     * 描述：生成字符串
     *
     * @param arg0 字符串元素
     * @param arg1 生成个数
     * @param arg2 间隔符号
     * @return
     */
    private static String createStr(String arg0, int arg1, String arg2) {
        if (arg0 == null) {
            return "";
        } else {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < arg1; i++) {
                if (arg2 == null) {
                    arg2 = "";
                }
                sb.append(arg0).append(arg2);
            }
            if (sb.length() > 0) {
                sb.delete(sb.lastIndexOf(arg2), sb.length());
            }

            return sb.toString();
        }
    }

    /**
     * 描述：数字格式化
     *
     * @param num     数字
     * @param pattern 格式
     * @return
     */
    public static String format(double num, String pattern) {
        NumberFormat fmt = null;
        if (pattern != null && pattern.length() > 0) {
            fmt = new DecimalFormat(pattern);
        } else {
            fmt = new DecimalFormat();
        }
        return fmt.format(num);
    }

    /**
     * 求浮点数的权重
     *
     * @param number
     * @return
     */
    public static double weight(double number) {
        if (number == 0) {
            return 1;
        }

        double e = Math.log10(Math.abs(number));
        int n = Double.valueOf(Math.floor(e)).intValue();
        double weight = 1;
        if (n > 0) {
            for (int i = 0; i < n; i++) {
                weight *= 10;
            }
        } else {
            for (int i = 0; i > n; i--) {
                weight /= 10;
            }
        }
        return weight;
    }

    /**
     * 获得权重的单位
     *
     * @param scale
     * @return
     */
    public static String unit(double scale) {
        if (scale == 1 || scale == 0) {
            return "";// 不设置单位倍率单位，使用基准单位
        }
        String[] units = new String[]{"十", "百", "千", "万", "十万", "百万", "千万", "亿", "十亿", "百亿", "千亿", "兆"};
        String[] units2 = new String[]{"十分", "百分", "千分", "万分", "十万分", "百万分", "千万分"};
        double e = Math.log10(scale);
        int position = Double.valueOf(Math.ceil(e)).intValue();
        if (position >= 1 && position <= units.length) {
            return units[position - 1];
        } else if (position <= -1 && -position <= units2.length) {
            return units2[-position - 1];
        } else {
            return "无量";
        }
    }

    /**
     * 获得浮点数的缩放比例
     *
     * @param num
     * @return
     */
    public static double scale(double num) {
        double absValue = Math.abs(num);
        // 无需缩放
        if (absValue < 10000 && absValue >= 1) {
            return 1;
        }
        // 无需缩放
        else if (absValue < 1 && absValue > 0.0001) {
            return 1;
        } else {
            return weight(num) / 10;
        }
    }

    /**
     * 获得缩放后并且格式化的浮点数
     *
     * @param num
     * @param scale
     * @return
     */
    public static double scaleNumber(double num, double scale) {
        DecimalFormat df = null;
        if (scale == 1) {
            df = new DecimalFormat("#.0000");
        } else {
            df = new DecimalFormat("#.00");
        }
        double scaledNum = num / scale;
        return Double.valueOf(df.format(scaledNum));
    }

    /**
     * 产生n位随机数 TODO:性能不要，有待优化
     */
    public static String ramdomNumber(int n) {
        if (n <= 0) {
            throw new IllegalArgumentException("n must be positive !");
        }
        Random random = new Random();
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < n; i++) {
            result.append(random.nextInt(10));
        }
        return result.toString();
    }

    /**
     * 缩放1W倍
     */
    public static double changeTo(double number) {
        boolean flag = false;
        if (number < 0) {
            flag = true;
        }
        double value = Math.abs(number);
        value = value / 10000.0;
        if (flag) {
            value = Double.parseDouble("-" + value);
        }
        return value;
    }

    /**
     * 描述：缩放比例
     *
     * @param number
     * @param scale
     * @param points
     * @return
     */
    public static String scaleNumberToStr(double number, double scale, int points) {
        boolean flag = (number < 0);
        number = Math.abs(number);
        String result = "";
        DecimalFormat nbf3 = (DecimalFormat) NumberFormat.getInstance();// 默认格式
        nbf3.setGroupingUsed(false);
        nbf3.setMinimumFractionDigits(points);
        nbf3.setMaximumFractionDigits(points);
        double scaledNum = number / scale;
        result = nbf3.format(scaledNum);
        if (flag) {
            result = "-" + result;
        }
        return result;
    }

    /**
     * 04
     * 描述:两数相除 返回值:百分比 [0-100].[0-9][0-9]%
     */
    public static String getPercent(double a, double b) {
        if (a == 0 || b == 0) {
            return "0.00%";
        } else {
            //定义返回值:百分比 [0-100].[0-9][0-9]%
            String bfb = "";
            BigDecimal aBD = new BigDecimal(a + "");
            BigDecimal bBD = new BigDecimal(b + "");
            // filter=a.bcde      a/b 保留四位小数  并且四舍五入
            String filter = new BigDecimal(a + "").divide(new BigDecimal(b + ""), 4, RoundingMode.HALF_UP) + "";
            //如果a!=0
            if (!filter.substring(0, 1).equals("0")) {
                bfb = new BigDecimal(filter).multiply(new BigDecimal("100"))
                        .toString().substring(0, 6) + "%";
            } else {
                if (!filter.substring(2, 3).equals("0")) {//如果a=0 b!=0
                    bfb = new BigDecimal(filter).multiply(new BigDecimal("100"))
                            .toString().substring(0, 5) + "%";
                } else {
                    if (!filter.substring(3, 4).equals("0")) {//如果a,b=0 c!=0
                        bfb = new BigDecimal(filter).multiply(new BigDecimal("100"))
                                .toString().substring(0, 4) + "%";
                    } else {
                        if (!filter.substring(4, 5).equals("0")) {//如果a,b,c=0 d!=0
                            bfb = new BigDecimal(filter).multiply(new BigDecimal("100"))
                                    .toString().substring(0, 4) + "%";
                        } else {
                            if (!filter.substring(5, 6).equals("0")) {//如果a,b,c,d=0 e!=0
                                bfb = new BigDecimal(filter).multiply(new BigDecimal("100"))
                                        .toString().substring(0, 4) + "%";
                            } else {//如果a,b,c,d,e=0
                                bfb = "0.00%";
                            }
                        }
                    }
                }
            }
            return bfb;
        }
    }

    /**
     * 描述:去除小数点后无用的0 ，如果都是0去除小数点
     */
    public static String deleteNoUseZero(String str) {
        if (str.indexOf(".") > 0) {
            //正则表达
            //去掉后面无用的零
            str = str.replaceAll("0+?$", "");
            //如小数点后面全是零则去掉小数点
            str = str.replaceAll("[.]$", "");
        }
        return str;
    }

    public static int[] getIntervalNum(int start,int length){
        int[] rtn= new int[length] ;
        int end = start+length;
        for(int i=0;i<length;i++){
            rtn[i]=start;
            start++;
        }
        return rtn;
    }

    /**
     * 对数据单位进行转换
     *
     * @param number  数值
     * @param company 单位（元、人次 等......）
     * @author luchuan
     * @date 2025/9/3
     * @return 万元、万人次、亿元、亿人次
     */
    public static String formatNumber(Number number, String company) {

        BigDecimal bigDecimalNumber = new BigDecimal(number.doubleValue());
        String integerNumber = bigDecimalNumber.setScale(0, BigDecimal.ROUND_UP).toString();
        Integer length = integerNumber.length();
        if (length > 8) {
            BigDecimal resultNumber = new BigDecimal(integerNumber).divide(new BigDecimal(100000000), 2, BigDecimal.ROUND_UP);
            return resultNumber + "亿" + company;
        } else {
            if (length > 4) {
                BigDecimal resultNumber = new BigDecimal(integerNumber).divide(new BigDecimal(10000), 2, BigDecimal.ROUND_UP);
                return resultNumber + "万" + company;
            } else {
                return integerNumber + company;
            }
        }
    }

    /**
     * 对数据单位进行转换
     * @param flag 0：个级，默认；1：万级；2：亿级.
     *             非必传参数，不传的时候按照整数部分大于8为，则返回亿级，大于4位则返回万级。
     * @param number  数值（必传参数）
     * @param unit 单位（元、人次 等，必传参数）
     * @param scale 小数位长度（默认是两位，非必传参数）
     * @author yxq
     * @date 2025/9/3
     * @return 万元、万人次、亿元、亿人次
     */
    public static NumberUnitEntity formmatNumberUnit(String number, String unit, Integer flag, Integer scale) {
        NumberUnitEntity numberUnitEntity = new NumberUnitEntity();
        String num = number;
        String unitC = unit;
        if(null==flag){
            BigDecimal bigDecimalNumber = new BigDecimal(number);
            String integerNumber = bigDecimalNumber.setScale(0, BigDecimal.ROUND_HALF_UP).toString();
            Integer length = integerNumber.length();
            if (length > 8) {
                num = bigdecimalDividRhu(new BigDecimal(number),MATH_YI_LEVLE,scale).toPlainString();
                unitC = "亿"+unit;
            }else if(length > 4) {
                num=bigdecimalDividRhu(new BigDecimal(number),MATH_WAN_LEVLE,scale).toPlainString();
                unitC="万"+unit;
            }
        }else{
            int flagInt = flag.intValue();
            switch (flagInt){
                case 1:
                    num=bigdecimalDividRhu(new BigDecimal(number),MATH_WAN_LEVLE,scale).toPlainString();
                    unitC="万"+unit;
                    break;
                case 2:
                    num=bigdecimalDividRhu(new BigDecimal(number),MATH_YI_LEVLE,scale).toPlainString();
                    unitC="亿"+unit;
                    break;
                default:
                    break;
            }
        }
        numberUnitEntity.setNumber(num);
        numberUnitEntity.setUnit(unitC);
        return numberUnitEntity;
    }

    /**
     * @description: 两个bigdecimal数相除，四舍五入，小数位数默认是2位,小数位数中末尾是0的则去掉
     * @author yxq
     * @date 2025/5/31
     * @version 1.0
     */
    public static BigDecimal bigdecimalDividRhu(BigDecimal divisor,BigDecimal dividend,Integer scale){
        if(null == divisor||null == dividend){
            return null;
        }
        if(dividend.compareTo(BigDecimal.ZERO)==0){
            return null;
        }

        if(null == scale){
            scale = 2;
        }
        BigDecimal result = divisor.divide(dividend,scale,BigDecimal.ROUND_HALF_UP).stripTrailingZeros();
        return result;
    }

    /**
     * 对数据保留几位小数
     *
     * @param divisor  除数
     * @param dividend 被除数
     * @param bit      保留位数
     * @return
     * @author luchuan
     * @date 2025/9/3
     */
    public static String reservedBits(Number dividend, Number divisor, int bit) {

        if (dividend.intValue() == 0 || divisor.intValue() == 0) {
            return "0";
        }
        //除数
        BigDecimal bigDecimalDivisor = new BigDecimal(divisor.doubleValue());
        //被除数
        BigDecimal bigDecimalDividend = new BigDecimal(dividend.doubleValue());

        BigDecimal result = bigDecimalDividend.divide(bigDecimalDivisor, bit, BigDecimal.ROUND_UP);

        return result.toString();
    }


    /**
     * 本期 和 本期同比  计算往期总量
     *
     * @param thisNumber:本期
     * @param thisYOY:本期同比
     * @return
     * @author luchuan
     * @date 2025/9/4
     */
    public static String getLastNumber(Number thisNumber, Number thisYOY, int bit) {
        BigDecimal bigDecimalThisNumber = new BigDecimal(thisNumber.doubleValue());
        BigDecimal bigDecimalThisYOY = new BigDecimal(thisYOY.doubleValue());

        /**
         *     100*本期
         *	------------- = 往期总量
         *	 本期同比+100
         */
        BigDecimal bigDecimalDivisor = new BigDecimal(100).multiply(bigDecimalThisNumber);
        BigDecimal bigDecimalDividend = bigDecimalThisYOY.add(new BigDecimal(100));

        BigDecimal result = bigDecimalDivisor.divide(bigDecimalDividend, bit, BigDecimal.ROUND_UP);

        return result.toString();
    }

    /**
     * 计算同比量
     *
     * @param thisNumber:本期
     * @return
     * @author luchuan
     * @date 2025/9/4
     */
    public static String getNumberYOY(Number thisNumber, Number lastNumber, int bit) {

        BigDecimal bigDecimalThisNumber = new BigDecimal(thisNumber.doubleValue());
        BigDecimal bigDecimalLastNumber = new BigDecimal(lastNumber.doubleValue());

        /**
         *            本期-往期
         *	同比 =   ------------- *100
         *	        	往期
         */
        BigDecimal bigDecimalDivisor = bigDecimalThisNumber.subtract(bigDecimalLastNumber);


        BigDecimal result = bigDecimalDivisor.multiply(new BigDecimal(100)).divide(bigDecimalLastNumber, 2, BigDecimal.ROUND_UP);

        return result.toString();
    }

    /**
     * 返回乘以100后的整数,也就是返回百分比的数值，不返回百分比符号
     *
     * @param divisor  除数
     * @param dividend 被除数
     * @param bit      保留位数
     * @return
     * @author yangxiaoquan
     * @date 2025/12/22
     */
    public static int reservedPercentage(Number dividend, Number divisor, int bit) {

        if (dividend.intValue() == 0 || divisor.intValue() == 0) {
            return 0;
        }
        //除数
        BigDecimal bigDecimalDivisor = new BigDecimal(divisor.doubleValue());
        //被除数
        BigDecimal bigDecimalDividend = new BigDecimal(dividend.doubleValue());
        BigDecimal result = bigDecimalDividend.divide(bigDecimalDivisor, bit, BigDecimal.ROUND_UP);
        result = result.multiply(new BigDecimal(100));
        return result.intValue();
    }

    /**
     * 用NumberFormat来格式化double结果，这样转换成字符串就不会采用科学计数法。
     * @param d
     * @return
     */
    public static String doubleToStr(Double d) {
        if (d == null) {
            return "";
        }
        NumberFormat format = NumberFormat.getInstance();
        String s = format.format(d);
        return (s);
    }

    /**
     * 将0-10数字转换为零、一，二等大写
     * @return
     */
    public static String numberToUpper(int num){
        String[] upper = {"零","一","二","三","四","五","六","七","八","九"};
        char[] str = String.valueOf(num).toCharArray();
        String rstr = "";
        for (int i = 0; i < str.length; i++) {
            rstr = rstr + upper[Integer.parseInt(str[i] + "")];
        }
        return rstr;
    }

    // 月转化为大写
    public static String monthToUppder(int month) {
        if(month < 10) {
            return numberToUpper(month);
        } else if(month == 10){
            return "十";
        } else {
            return "十" + numberToUpper(month - 10);
        }
    }

    /**
     * 返回不包含百分比的百分比，
     * @param divisor  除数
     * @param dividend 被除数
     * @return String  返回字符串的小数形式数据
     * @author yangxiaoquan
     * @date 2025/09/24
     */

    public static String reservedPercentageDot(BigDecimal dividend, BigDecimal divisor) {
        return reservedPercentageDot(dividend,divisor,null);
    }

    /**
     * 返回不包含百分比的百分比，
     * @param divisor  除数
     * @param dividend 被除数
     * @param bit      保留位数，未乘以100的小数点后的长度，如设为4，则最后的结果是保留两位小数，默认是4
     * @return String  返回字符串的小数形式数据
     * @author yangxiaoquan
     * @date 2025/09/24
     */
    public static String reservedPercentageDot(BigDecimal dividend, BigDecimal divisor, Integer bit) {
        if(null == dividend || divisor == null){
            return null;
        }
        if(dividend.compareTo(BigDecimal.ZERO)==0){
            return "0";
        }
        if(divisor.compareTo(BigDecimal.ZERO)==0){
            return null;
        }
        if(null == bit){
            bit = 4;
        }
        BigDecimal result = dividend.divide(divisor, bit, BigDecimal.ROUND_UP);
        //使用tostring方法会变成科学计数法输出，所以用toPlainString
        return result.multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString();
    }

    public static int extractNumbers(String str) {
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            return Integer.parseInt(matcher.group());
        }
        return 0;
    }

    public static void main(String[] args) {
        String str = "5座轿车15";
        System.out.println(extractNumbers(str));
    }



}
