package com.vetti.common.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

/**
 * 通用单位转换工具类
 * 支持：长度、重量、时间、面积、体积、温度 等常见单位转换
 *
 * @author ID
 * @date 2025/9/15 22:59
 */
public class UnitConvertUtils {

    // ==================== 常量：单位换算系数（基于国际标准单位）====================
    // 长度单位：1米(m) = 对应单位的数量
    public static final BigDecimal M_TO_KM = new BigDecimal("0.001");    // 米 -> 千米
    public static final BigDecimal M_TO_CM = new BigDecimal("100");      // 米 -> 厘米
    public static final BigDecimal M_TO_MM = new BigDecimal("1000");     // 米 -> 毫米
    public static final BigDecimal M_TO_INCH = new BigDecimal("39.3701");// 米 -> 英寸
    public static final BigDecimal M_TO_FOOT = new BigDecimal("3.28084"); // 米 -> 英尺

    // 重量单位：1千克(kg) = 对应单位的数量
    public static final BigDecimal KG_TO_G = new BigDecimal("1000");     // 千克 -> 克
    public static final BigDecimal KG_TO_T = new BigDecimal("0.001");    // 千克 -> 吨
    public static final BigDecimal KG_TO_LB = new BigDecimal("2.20462"); // 千克 -> 磅（常衡）

    // 时间单位：1秒(s) = 对应单位的数量（修正为小数形式，避免解析错误）
    public static final BigDecimal S_TO_MS = new BigDecimal("1000");     // 秒 -> 毫秒
    public static final BigDecimal S_TO_MIN = new BigDecimal("0.016666666666666666"); // 秒 -> 分钟 (1/60)
    public static final BigDecimal S_TO_HOUR = new BigDecimal("0.0002777777777777778"); // 秒 -> 小时 (1/3600)
    public static final BigDecimal S_TO_DAY = new BigDecimal("0.000011574074074074073"); // 秒 -> 天 (1/86400)

    // 面积单位：1平方米(m²) = 对应单位的数量
    public static final BigDecimal M2_TO_CM2 = new BigDecimal("10000");  // 平方米 -> 平方厘米
    public static final BigDecimal M2_TO_KM2 = new BigDecimal("1e-6");   // 平方米 -> 平方千米
    public static final BigDecimal M2_TO_ACRE = new BigDecimal("0.000247105"); // 平方米 -> 英亩

    // 温度单位：转换公式（摄氏度℃ ↔ 华氏度℉）
    public static final BigDecimal C_TO_F_RATIO = new BigDecimal("1.8"); // ℃转℉系数
    public static final BigDecimal C_TO_F_OFFSET = new BigDecimal("32");  // ℃转℉偏移量


    /**
     * 通用单位转换方法（适用于“系数乘法”类型的转换，如长度、重量、面积等）
     * @param sourceValue 原始值（不可为null）
     * @param convertRatio 转换系数（如米转千米用 M_TO_KM）
     * @param scale 结果保留小数位数（默认2位）
     * @return 转换后的值（BigDecimal，避免精度丢失）
     */
    public static BigDecimal convertByRatio(BigDecimal sourceValue, BigDecimal convertRatio, Integer... scale) {
        // 1. 参数校验
        Objects.requireNonNull(sourceValue, "原始值不能为null");
        Objects.requireNonNull(convertRatio, "转换系数不能为null");
        int resultScale = scale.length > 0 ? scale[0] : 2;

        // 校验小数位数是否合法
        if (resultScale < 0) {
            throw new IllegalArgumentException("小数位数不能为负数: " + resultScale);
        }

        // 2. 计算：原始值 × 转换系数，四舍五入
        return sourceValue.multiply(convertRatio).setScale(resultScale, RoundingMode.HALF_UP);
    }


    /**
     * 温度转换（摄氏度 ↔ 华氏度）
     * @param sourceValue 原始温度值（不可为null）
     * @param sourceUnit 原始单位（支持 "C" 或 "F"）
     * @param targetUnit 目标单位（支持 "C" 或 "F"）
     * @param scale 结果保留小数位数（默认1位）
     * @return 转换后的温度值
     */
    public static BigDecimal convertTemperature(BigDecimal sourceValue, String sourceUnit, String targetUnit, Integer... scale) {
        // 1. 参数校验
        Objects.requireNonNull(sourceValue, "温度值不能为null");
        Objects.requireNonNull(sourceUnit, "原始单位不能为null");
        Objects.requireNonNull(targetUnit, "目标单位不能为null");

        if (!("C".equals(sourceUnit) || "F".equals(sourceUnit))) {
            throw new IllegalArgumentException("原始单位仅支持 'C'（摄氏度）或 'F'（华氏度），实际为: " + sourceUnit);
        }
        if (!("C".equals(targetUnit) || "F".equals(targetUnit))) {
            throw new IllegalArgumentException("目标单位仅支持 'C'（摄氏度）或 'F'（华氏度），实际为: " + targetUnit);
        }

        int resultScale = scale.length > 0 ? scale[0] : 1;
        if (resultScale < 0) {
            throw new IllegalArgumentException("小数位数不能为负数: " + resultScale);
        }

        if (sourceUnit.equals(targetUnit)) {
            return sourceValue.setScale(resultScale, RoundingMode.HALF_UP);
        }

        // 2. 转换逻辑
        BigDecimal result;
        if ("C".equals(sourceUnit) && "F".equals(targetUnit)) {
            // 摄氏度 → 华氏度：F = C × 1.8 + 32
            result = sourceValue.multiply(C_TO_F_RATIO).add(C_TO_F_OFFSET);
        } else {
            // 华氏度 → 摄氏度：C = (F - 32) / 1.8
            result = sourceValue.subtract(C_TO_F_OFFSET)
                    .divide(C_TO_F_RATIO, 10, RoundingMode.HALF_UP);
        }

        // 3. 保留小数位数
        return result.setScale(resultScale, RoundingMode.HALF_UP);
    }


    // ==================== 便捷方法：简化常用转换调用 ====================
    /**
     * 米 → 千米
     */
    public static BigDecimal meterToKilometer(BigDecimal meter, Integer... scale) {
        return convertByRatio(meter, M_TO_KM, scale);
    }

    /**
     * 千克 → 磅
     */
    public static BigDecimal kilogramToPound(BigDecimal kg, Integer... scale) {
        return convertByRatio(kg, KG_TO_LB, scale);
    }

    /**
     * 秒 → 分钟
     */
    public static BigDecimal secondToMinute(BigDecimal second, Integer... scale) {
        return convertByRatio(second, S_TO_MIN, scale);
    }

    /**
     * 秒 → 小时
     */
    public static BigDecimal secondToHour(BigDecimal second, Integer... scale) {
        return convertByRatio(second, S_TO_HOUR, scale);
    }

    /**
     * 摄氏度 → 华氏度
     */
    public static BigDecimal celsiusToFahrenheit(BigDecimal celsius, Integer... scale) {
        return convertTemperature(celsius, "C", "F", scale);
    }

    /**
     * 华氏度 → 摄氏度
     */
    public static BigDecimal fahrenheitToCelsius(BigDecimal fahrenheit, Integer... scale) {
        return convertTemperature(fahrenheit, "F", "C", scale);
    }

}
