package com.zt.plat.module.qms.core.util.number;

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

/**
 * 有效数字格式化
 */
public class EffectiveNumberFormatter {
	
	/**
     * 处理数字：先保留固定小数位，再保留有效数字。
     * 两步均使用银行家舍入法 (HALF_EVEN)。
     *
     * @param numberStr 输入的数字字符串
     * @param decimalPlaces 第一步：要保留的小数位数
     * @param effectiveDigit 第二步：要保留的有效数字位数
     * @return 处理后的字符串结果
     */
    public static String formatNumber(String numberStr, int decimalPlaces, int effectiveDigit) {
        if (numberStr == null || numberStr.trim().isEmpty()) {
            throw new IllegalArgumentException("输入字符串不能为空");
        }

        try {
            // 1. 转换为 BigDecimal
            BigDecimal value = new BigDecimal(numberStr.trim());

            
            // 2.处理数据
            return formatNumber(value, decimalPlaces, effectiveDigit);

        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无效的数字格式: " + numberStr, e);
        }
    }

	/**
     * 处理数字：先保留固定小数位，再保留有效数字。
     * 两步均使用银行家舍入法 (HALF_EVEN)。
     *
     * @param value 输入的数字
     * @param decimalPlaces 第一步：要保留的小数位数
     * @param effectiveDigit 第二步：要保留的有效数字位数
     * @return 处理后的字符串结果
     */
    public static String formatNumber(BigDecimal value, int decimalPlaces, int effectiveDigit) {

        // 处理 0 的特殊情况
        if (value.compareTo(BigDecimal.ZERO) == 0) {
            // 0 的有效数字通常视为 0，直接返回对应有效小数位的 0
            return value.setScale(effectiveDigit, RoundingMode.HALF_EVEN).toPlainString();
        }

     // --- 第一步：保留固定小数位 ---
        // 使用 HALF_EVEN (银行家算法)
        BigDecimal step1 = value.setScale(decimalPlaces, RoundingMode.HALF_EVEN);

        // 如果结果为0，直接返回 (0.00...)
        if (step1.compareTo(BigDecimal.ZERO) == 0) {
            return step1.setScale(effectiveDigit, RoundingMode.HALF_EVEN).toPlainString();
        }

        // --- 第二步：针对小数部分保留有效数字 ---
        
        // 1. 获取当前标度 (小数位数)
        int currentScale = step1.scale();
        if (currentScale <= 0) {
            // 如果没有小数部分，直接返回有效小数位的0
            return step1.setScale(effectiveDigit, RoundingMode.HALF_EVEN).toPlainString();
        }

        // 2. 将数字转换为纯小数字符串进行分析
        // toPlainString 确保不使用科学计数法
        String plainStr = step1.toPlainString();
        
        // 分离整数和小数部分
        String[] parts = plainStr.split("\\.");
        String fractionalPart = (parts.length > 1) ? parts[1] : "";
        
        // 如果第一步处理后小数部分为空或全0（理论上setScale后不会空，但可能全0）
        if (fractionalPart.isEmpty()) {
            return step1.setScale(effectiveDigit, RoundingMode.HALF_EVEN).toPlainString();
        }

        // 3. 寻找小数部分第一个非零数字的位置
        int firstNonZeroIndex = -1;
        for (int i = 0; i < fractionalPart.length(); i++) {
            if (fractionalPart.charAt(i) != '0') {
                firstNonZeroIndex = i;
                break;
            }
        }

        // 如果小数部分全是0 (例如 1.0000)，直接返回有效小数位的0
        if (firstNonZeroIndex == -1) {
            return step1.setScale(effectiveDigit, RoundingMode.HALF_EVEN).toPlainString();
        }

        // 4. 计算新的目标小数位数 (Scale)
        // 逻辑：保留从 firstNonZeroIndex 开始的 decimalSignificantDigits 个数字
        // 目标长度 = (第一个非零数的索引) + (要保留的有效位数)
        // 例如: 0.001234, firstNonZero=2 ('1'), 要留2位 -> 目标长度 2+2=4 -> 0.0012
        int targetFractionalLength = firstNonZeroIndex + effectiveDigit;

        // 如果计算出的目标长度超过了当前小数长度，说明不需要截断（甚至可能需要补0，但setScale会自动补0）
        // 如果目标长度小于等于0（极端情况），至少保留到第一个非零位？
        // 按照常规逻辑，如果 targetFractionalLength <= firstNonZeroIndex，意味着保留0位有效数字？
        // 这里假设用户输入的 decimalSignificantDigits >= 1
        
        int newScale = targetFractionalLength;

        // 5. 执行第二次舍入
        // 注意：如果 newScale > currentScale, setScale 会补0
        // 如果 newScale < currentScale, setScale 会截断并使用 RoundingMode
        BigDecimal finalResult = step1.setScale(newScale, RoundingMode.HALF_EVEN);
        
        // 6.如果小数位数大于精度，则在执行舍入
        if (finalResult.scale() > decimalPlaces) {
        	finalResult = finalResult.setScale(decimalPlaces, RoundingMode.HALF_EVEN);
		}
        
        return finalResult.toPlainString();

        /**
        // --- 第一步：保留固定小数位 ---
        // 使用 HALF_EVEN (银行家算法)
        BigDecimal step1 = value.setScale(decimalPlaces, RoundingMode.HALF_EVEN);
        
        // --- 第二步：保留有效数字 ---
        // 基于第一步的结果计算有效数字
        int currentPrecision = step1.precision();
        int currentScale = step1.scale();
        
        // 计算目标 scale: newScale = currentScale + (targetSignificance - currentPrecision)
        int targetScale = currentScale + (effectiveDigit - currentPrecision);
        
        // 再次使用 HALF_EVEN 进行舍入
        // 注意：如果 targetScale 小于 0，setScale 会正确处理（例如变成 1200）
        BigDecimal step2 = step1.setScale(targetScale, RoundingMode.HALF_EVEN);
        return step2.toPlainString();
        **/

    }
    
    /**
     * 保留有效数字
     * @param value 输入的数字
     * @param effectiveDigit 要保留的有效数字位
     * @return
     */
//    public static String formatNumber(BigDecimal value, int effectiveDigit) {
//    	//是总位数
//    	int currentPrecision = value.precision();
//    	//获取当前标度 (小数位数)
//        int currentScale = value.scale();
//        
//        // 计算目标 scale: newScale = currentScale + (targetSignificance - currentPrecision)
//        int targetScale = currentScale + (effectiveDigit - currentPrecision);
//        
//        // 再次使用 HALF_EVEN 进行舍入
//        // 注意：如果 targetScale 小于 0，setScale 会正确处理（例如变成 1200）
//        BigDecimal result = value.setScale(targetScale, RoundingMode.HALF_EVEN);
//
//        return result.toPlainString();
//    }
    
    /**
     * 保留有效数字
     * @param value 输入的数字
     * @param effectiveDigit 要保留的有效数字位
     * @return
     */
    public static BigDecimal formatNumber2(BigDecimal value, int decimalPlaces, int effectiveDigit) {

        // 如果结果为0，直接返回 (0.00...)
        if (value.compareTo(BigDecimal.ZERO) == 0) {
            return value.setScale(effectiveDigit, RoundingMode.HALF_EVEN);
        }

        // 1. 获取当前标度 (小数位数)
        int currentScale = value.scale();
        if (currentScale <= 0) {
            // 如果没有小数部分，直接返回整数
            return value.setScale(effectiveDigit, RoundingMode.HALF_EVEN);
        }

        // 2. 将数字转换为纯小数字符串进行分析
        // toPlainString 确保不使用科学计数法
        String plainStr = value.toPlainString();
        
        // 分离整数和小数部分
        String[] parts = plainStr.split("\\.");
        String fractionalPart = (parts.length > 1) ? parts[1] : "";
        
        // 如果第一步处理后小数部分为空或全0（理论上setScale后不会空，但可能全0）
        if (fractionalPart.isEmpty()) {
            return value.setScale(effectiveDigit, RoundingMode.HALF_EVEN);
        }

        // 3. 寻找小数部分第一个非零数字的位置
        int firstNonZeroIndex = -1;
        for (int i = 0; i < fractionalPart.length(); i++) {
            if (fractionalPart.charAt(i) != '0') {
                firstNonZeroIndex = i;
                break;
            }
        }

        // 如果小数部分全是0 (例如 1.0000)，则不需要再做有效数字截断，直接返回
        if (firstNonZeroIndex == -1) {
            return value.setScale(effectiveDigit, RoundingMode.HALF_EVEN);
        }

        // 4. 计算新的目标小数位数 (Scale)
        // 逻辑：保留从 firstNonZeroIndex 开始的 decimalSignificantDigits 个数字
        // 目标长度 = (第一个非零数的索引) + (要保留的有效位数)
        // 例如: 0.001234, firstNonZero=2 ('1'), 要留2位 -> 目标长度 2+2=4 -> 0.0012
        int targetFractionalLength = firstNonZeroIndex + effectiveDigit;

        // 如果计算出的目标长度超过了当前小数长度，说明不需要截断（甚至可能需要补0，但setScale会自动补0）
        // 如果目标长度小于等于0（极端情况），至少保留到第一个非零位？
        // 按照常规逻辑，如果 targetFractionalLength <= firstNonZeroIndex，意味着保留0位有效数字？
        // 这里假设用户输入的 decimalSignificantDigits >= 1
        
        int newScale = targetFractionalLength;

        // 5. 执行第二次舍入
        // 注意：如果 newScale > currentScale, setScale 会补0
        // 如果 newScale < currentScale, setScale 会截断并使用 RoundingMode
        BigDecimal finalResult = value.setScale(newScale, RoundingMode.HALF_EVEN);

        // 6.如果小数位数大于精度，则在执行舍入
        if (finalResult.scale() > decimalPlaces) {
        	finalResult = finalResult.setScale(decimalPlaces, RoundingMode.HALF_EVEN);
		}
        return finalResult;
    }

}
