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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

import java.math.BigDecimal;
import java.util.List;

/**
 * 数字的工具类，补全 {@link cn.hutool.core.util.NumberUtil} 的功能
 *
 * @author 芋道源码
 */
public class NumberUtils {

    public static Long parseLong(String str) {
        return StrUtil.isNotEmpty(str) ? Long.valueOf(str) : null;
    }

    public static Integer parseInt(String str) {
        return StrUtil.isNotEmpty(str) ? Integer.valueOf(str) : null;
    }

    public static int hexToDecimal(String hex) {
        if (hex.matches("-?\\d+(\\.\\d+)?")){
            return Integer.parseInt(hex);
        }
        // 去除可能的前缀和空格
        hex = hex.trim().replaceFirst("0x", "").replaceFirst("#", "");
        // 使用Integer.parseInt转换
        return Integer.parseInt(hex, 16);
    }

    public static boolean isAllNumber(List<String> values) {
        if (CollUtil.isEmpty(values)) {
            return false;
        }
        for (String value : values) {
            if (!NumberUtil.isNumber(value)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 通过经纬度获取地球上两点之间的距离
     *
     * 参考 <<a href="https://gitee.com/dromara/hutool/blob/1caabb586b1f95aec66a21d039c5695df5e0f4c1/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java">DistanceUtil</a>> 实现，目前它已经被 hutool 删除
     *
     * @param lat1 经度1
     * @param lng1 纬度1
     * @param lat2 经度2
     * @param lng2 纬度2
     * @return 距离，单位：千米
     */
    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
        double radLat1 = lat1 * Math.PI / 180.0;
        double radLat2 = lat2 * Math.PI / 180.0;
        double a = radLat1 - radLat2;
        double b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
        double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        distance = distance * 6378.137;
        distance = Math.round(distance * 10000d) / 10000d;
        return distance;
    }

    /**
     * 提供精确的乘法运算
     *
     * 和 hutool {@link NumberUtil#mul(BigDecimal...)} 的差别是，如果存在 null，则返回 null
     *
     * @param values 多个被乘值
     * @return 积
     */
    public static BigDecimal mul(BigDecimal... values) {
        for (BigDecimal value : values) {
            if (value == null) {
                return null;
            }
        }
        return NumberUtil.mul(values);
    }

    public static long extractNumber(String code) {
        int numberEnd = code.length() - 1;
        while (numberEnd >= 0 && Character.isDigit(code.charAt(numberEnd))) {
            numberEnd--;
        }
        String numberStr = code.substring(numberEnd + 1);
        return numberStr.isEmpty() ? 0 : Long.parseLong(numberStr);
    }


    public static String formatNumber(String numberStr) {
        // 检查字符串是否包含小数点
        if (numberStr.contains(".")) {
            // 包含小数点，转换为double后保留一位小数
            try {
                double number = Double.parseDouble(numberStr);
                // 使用String.format保留一位小数
                return String.format("%.1f", number);
            } catch (NumberFormatException e) {
                // 如果转换失败，返回原字符串
                return numberStr;
            }
        } else {
            // 不包含小数点，直接返回原字符串
            return numberStr;
        }
    }
    public static boolean isConvertibleToDouble(String str) {
        // 空值、空字符串直接返回false
        if (str == null || str.trim().isEmpty()) {
            return false;
        }
        try {
            // 尝试解析为double，解析成功则返回true
            Double.parseDouble(str.trim());
            return true;
        } catch (NumberFormatException e) {
            // 解析失败（非数字格式）返回false
            return false;
        }
    }
}
