package com.smppw.utils;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import com.smppw.constants.IndicatorConst;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wangzaijun
 * @date 2023/5/9 18:48
 * @description 数据处理工具
 */
public class DataUtil {
    /**
     * 无限接近0的数的除法
     * created by wangzaijun on 20230327
     *
     * @param divisor  除数
     * @param dividend 被除数
     * @return /
     */
    public static Double divNearZeroValue(Double divisor, Double dividend) {
        Double value = null;
        if (divisor != null && dividend != null && Math.abs(dividend) > IndicatorConst.MIN_DENOMINATOR_VALUE) {
            value = handleOverflowData(divisor / dividend);
        }
        return value;
    }

    /**
     * 处理分母为0时根据分子的值来返回对应的值
     *
     * @param value 分子
     * @return java.lang.Double
     */
    public static Double handleZeroValue(Double value) {
        if (value == null || value.isInfinite() || value.isNaN()) {
            return null;
        } else {
            double result = value / IndicatorConst.MIN_DENOMINATOR_VALUE;
            return handleOverflowData(result);
        }
    }

    /**
     * 处理数据防止溢出，并返回结果
     *
     * @param value 待加工返回值
     * @return java.lang.Double
     */
    public static Double handleOverflowData(Double value) {
        if (value.compareTo(IndicatorConst.MAX_INDICATOR_VALUE) > 0) {
            return IndicatorConst.MAX_INDICATOR_VALUE;
        } else if (value.compareTo(IndicatorConst.MIN_INDICATOR_VALUE) < 0) {
            return IndicatorConst.MIN_INDICATOR_VALUE;
        } else {
            return value;
        }
    }

    /**
     * 分组
     *
     * @param groupNumber 最大组数，0的左右两边平均
     * @param space       计算步长的
     * @param max         最大值
     * @param min         最新值
     * @return /
     * @see RangeUtils#groupNumberLimitCondition(int, double, double, double)
     * @deprecated 存在问题
     */
    @Deprecated
    public static List<Pair<Double, Double>> groupNumberLimitCondition(int groupNumber, double space, int max, int min) {
        List<Pair<Double, Double>> dates = ListUtil.list(true);
        int[] rightRange;
        int rightMin = 0;
        int rightMax = 0;
        if (max >= 0) {
            rightMax = max * 100;
        } else {
            rightMin = max * 100;
        }
        rightRange = NumberUtil.range(rightMin, rightMax, (int) (space * 100));
        int[] leftRange;
        int leftMin = 0;
        int leftMax = 0;
        if (min >= 0) {
            leftMax = min * 100;
        } else {
            leftMin = min * 100;
        }
        leftRange = NumberUtil.range(leftMin, leftMax, (int) (space * 100));
        for (int i = 0; i < rightRange.length; i++) {
            if (rightRange[i] == rightMin / 100.0) {
                continue;
            }
            if (i == (groupNumber / 2) - 1) {
                dates.add(Pair.of(rightRange[i] / 100.0, (double) rightMax / 100.0));
                break;
            }
            double key = i == rightRange.length - 1 ? rightMin / 100.0 : (rightRange[i] / 100.0);
            double value = i == rightRange.length - 1 ? rightMax / 100.0 : (rightRange[i + 1] / 100.0);
            if (Objects.equals(key, value)) {
                continue;
            }
            dates.add(Pair.of(key, value));
        }

        for (int i = 0; i < leftRange.length; i++) {
            if (leftRange[i] == leftMax / 100.0) {
                continue;
            }
            if (i == (groupNumber / 2) - 1) {
                dates.add(Pair.of((double) leftMin / 100.0, leftRange[i] / 100.0));
                break;
            }
            double key = i == leftRange.length - 1 ? leftMin / 100.0 : (leftRange[i + 1] / 100.0);
            double value = i == leftRange.length - 1 ? leftMax / 100.0 : leftRange[i] / 100.0;
            if (Objects.equals(key, value)) {
                continue;
            }
            dates.add(Pair.of(key, value));
        }
        return dates.stream().sorted(Comparator.comparing(Pair::getValue)).collect(Collectors.toList());
    }

    /**
     * 构建返回结果
     *
     * @param dates  /
     * @param values 值对象列表
     * @return /
     */
    public static List<Map<String, Object>> buildValue(List<Pair<Double, Double>> dates, List<Double> values) {
        List<Map<String, Object>> dataList = ListUtil.list(true);
        long total = values.stream().filter(Objects::nonNull).count();
        for (Pair<Double, Double> date : dates) {
            // 元素小于0 的 左闭右开区间，元素大于0 的 左开右闭区间，等于0的特殊处理
            long num = values.stream().filter(Objects::nonNull).map(e -> e * 100d)
                    .filter(e -> (e < 0d && e >= date.getKey() && e < date.getValue())
                            || (e > 0d && e > date.getKey() && e <= date.getValue())
                            || e == 0d && e.equals(date.getKey())).count();
            dataList.add(MapUtil.<String, Object>builder("date", date.getKey() + "%~" + date.getValue() + "%").put("num", num)
                    .put("ratio", BigDecimalUtils.divide(BigDecimalUtils.toBigDecimal(num), BigDecimalUtils.toBigDecimal(total))).build());
        }
        return dataList;
    }
}
