package com.xisc.pm.infra.util;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.xisc.pm.infra.constant.Constants;
import io.choerodon.core.exception.CommonException;
import io.choerodon.core.exception.ExceptionResponse;
import org.apache.commons.lang3.StringUtils;
import org.hzero.boot.platform.lov.adapter.LovAdapter;
import org.hzero.boot.platform.lov.dto.LovValueDTO;
import org.hzero.core.base.BaseConstants;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public class Utils {
    
    public static final String SPLIT_CHAR = "###";
    
    private Utils() {
    }

    /**
     * 判断两个区间是否相交
     *
     * @param firstStartFrom  区间1的起
     * @param firstStartTo    区间1的止
     * @param secondStartFrom 区间2的起
     * @param secondStartTo   区间2的止
     * @return 相交则返回true
     */
    public static boolean isIntersect(BigDecimal firstStartFrom, BigDecimal firstStartTo, BigDecimal secondStartFrom, BigDecimal secondStartTo) {
        if (firstStartFrom == null || firstStartTo == null || secondStartFrom == null || secondStartTo == null) {
            return false;
        }
        BigDecimal maxStart = firstStartFrom.compareTo(secondStartFrom) > 0 ? firstStartFrom : secondStartFrom;
        BigDecimal minStart = firstStartTo.compareTo(secondStartTo) < 0 ? firstStartTo : secondStartTo;
        return maxStart.compareTo(minStart) <= 0;
    }
    
    public static boolean isRange(BigDecimal value , BigDecimal begin , BigDecimal end) {
        if(begin == null || end == null || value == null) {
            return false ;
        }
        if(value.compareTo(begin) >= 0 && value.compareTo(end) <= 0) {
            return true;
        }
        return true ;
    }
    
    /**
     * 设计产线号转换为轧制产线号
     * @param mscLineNo 4位
     * @return 2位轧制产线号
     */
    public static String mscLineNoToRoolLineNo(String mscLineNo) {
        if(StringUtils.isBlank(mscLineNo) || mscLineNo.length() < 2) {
            return null ;
        }
        // 轧制产线号为设计产线号的后两位
        String rollLineNo = mscLineNo.substring(mscLineNo.length() - 2);
        return rollLineNo;
    }

    /**
     * 判断数字的小数位数
     * @param number 数字
     * @param digit 小数位数
     * @return true
     */
    public static boolean verifyDecimalPlaces(BigDecimal number, int digit) {
        if (number == null) {
            return true;
        }
        String[] split = number.toString().split(".");
        if (split.length > 1) {
            return split[1].length() <= digit;
        }
        return true;
    }
    
    public static Long getYesOrNo(String value) {
        if(StringUtils.isBlank(value)) {
            return null;
        }
        if(BaseConstants.Flag.YES.toString().equals(value) || BaseConstants.FlagChar.YES.equals(value)) {
            return BaseConstants.Flag.YES.longValue();
        } else {
            return BaseConstants.Flag.NO.longValue();
        }
    }
    
    public static boolean equals(String obj1 , String obj2) {
        if(obj1 == null && obj2 == null) {
            return true ;
        }
        if(obj1 != null && obj1.equals(obj2)) {
            return true ;
        }
        return false ;
    }
    
    public static BigDecimal maxValue(BigDecimal ...value) {
        BigDecimal max = null ;
        for (BigDecimal val : value) {
            if(max == null || max.compareTo(val) <= 0) {
                max = val ;
            }
        }
        return max;
    }
    
    public static BigDecimal minValue(BigDecimal ...value) {
        BigDecimal min = null ;
        for (BigDecimal val : value) {
            if(min == null || min.compareTo(val) >= 0) {
                min = val ;
            }
        }
        return min;
    }
    
    public static BigDecimal[] splitBigDecimal(BigDecimal totalAmount, int n) {
        if (n <= 0) {
            throw new IllegalArgumentException("份额数必须大于0");
        }
        BigDecimal[] result = new BigDecimal[n];
        BigDecimal quotient = totalAmount.divide(new BigDecimal(n), 0, RoundingMode.DOWN); // 整除
        BigDecimal remainder = totalAmount.remainder(new BigDecimal(n)); // 余数
        for (int i = 0; i < n; i++) {
            if (i == n - 1) {
                result[i] = quotient.add(remainder); // 最后一个份额加上余数
            } else {
                result[i] = quotient;
            }
        }
        return result;
    }
    
    public static void main(String[] args) {
        BigDecimal totalAmount = new BigDecimal("2"); // 示例总金额
        int n = 4; // 分成4份
 
        BigDecimal[] result = splitBigDecimal(totalAmount, n);
 
        // 输出结果
        for (int i = 0; i < result.length; i++) {
            System.out.println("份额 " + (i + 1) + ": " + result[i]);
        }
    }
    
    public static Map<String , String> getLovMeaning(LovAdapter lovAdapter , Long tenantId, String... lovCode ){
        Map<String , String> data = new HashMap<String, String>();
        for (String code : lovCode) {
            List<LovValueDTO> lovValueDto = lovAdapter.queryLovValue(code, tenantId);
            for (LovValueDTO value : lovValueDto) {
                String key = code + SPLIT_CHAR + value.getValue();
                data.put(key, value.getMeaning());
            }
        }
        return data ;
    }
    
    public static <T> void setMeaning(Map<String ,String> data , String lovCode ,T t , Consumer<String> consumer , Function<T, Object> function){
        Object obj = function.apply(t);
        if(obj != null) {
            String key = lovCode + SPLIT_CHAR + obj.toString();
            if(data != null && data.containsKey(key)) {
                consumer.accept(data.get(key));
            } else {
                consumer.accept(obj.toString());
            }
        }
    }
    
    /**
     * 剔除后三位
     * @param str
     * @return
     */
    public static String removeLastThreeChars(String str) {
        // 检查字符串长度是否至少为3
        if (str.length() >= 3) {
            // 使用substring方法去除最后三位
            return str.substring(0, str.length() - 3);
        } else {
            // 如果字符串长度小于3，则返回空字符串或原始字符串（根据需求决定）
            // 这里返回空字符串作为示例
            return str;
        }
    }
    
    /**
     * 剔除后三位
     * @param str
     * @return
     */
    public static String removeLastSecondChars(String str) {
        // 检查字符串长度是否至少为2
        if (str.length() >= 2) {
            // 使用substring方法去除最后三位
            return str.substring(0, str.length() - 2);
        } else {
            // 如果字符串长度小于2，则返回空字符串或原始字符串（根据需求决定）
            // 这里返回空字符串作为示例
            return str;
        }
    }

    /**
     * 转换接口报错对象
     *
     * @param res
     * @return
     */
    public static ExceptionResponse getExceptionResponse(ResponseEntity<String> res) {
        try {
            if (res.getStatusCode().is2xxSuccessful() && !HttpStatus.NO_CONTENT.equals(res.getStatusCode())) {
                ExceptionResponse response = new ObjectMapper().readValue(res.getBody(), ExceptionResponse.class);
                return response;
            }
        } catch (Exception e) {
            throw new CommonException("解析ExceptionResponse对象失败, 原因为:{0}",e.getMessage());
        }
        return new ExceptionResponse();
    }

    /**
     * 获取值对象下标
     *
     * @param array
     * @param value
     * @return
     */
    public static int findIndex(String[] array, String value) {
        for (int i = 0; i < array.length; i++) {
            if (array[i].equals(value)) {
                return i;
            }
        }
        // 如果没有找到，返回-1
        return -1;
    }

    /**
     * 判断是否是合并板坯
     *
     * @param virtualSlabNo
     * @return
     */
    public static boolean isMergeSlab(String virtualSlabNo) {
        // 合并板坯以M开头，第二位不是字母
        return virtualSlabNo.startsWith("M") && !Character.isLetter(virtualSlabNo.charAt(1));
    }

    /**
     * 截取日期
     * @param date
     * @return
     */
    public static String transToBatchDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateStr = sdf.format(date);
        // 获取小时部分
        int hour = date.getHours();

        // 根据小时部分添加后缀
        String suffix;
        if (hour >= 0 && hour < 8) {
            suffix = "1";
        } else if (hour >= 8 && hour < 16) {
            suffix = "2";
        } else {
            suffix = "3";
        }
        return dateStr + suffix;
    }

    /**
     * 钢板号截取后三位中为0的下标
     *
     * @param plateNo
     * @return
     */
    public static int findPlatNoIndexZero(String plateNo) {
        StringBuilder plateNoBuilder = new StringBuilder(plateNo.substring(plateNo.length() - 3));
        // 找出为0的下标
        int index = -1;
        for (int k = 0; k < plateNoBuilder.length(); k++) {
            if (plateNoBuilder.charAt(k) == '0') {
                index = k;
                break;
            }
        }
        if (index == -1) {
            throw new CommonException("pm.small_plt_pos_001", plateNo);
        }
        return index;
    }

    public static <T> List<List<T>> splitList(List<T> results,
            long batchSize) {
        List<List<T>> res = new ArrayList<>();
        int allCount = results.size();
        long limit = (allCount + batchSize - 1) / batchSize;
        Stream.iterate(0, n -> n + 1).limit(limit).forEach(i -> {
            List<T> subList = results.stream().skip(i * batchSize)
                    .limit(batchSize).collect(Collectors.toList());
            res.add(subList);
        });
        return res;
    }

    /**
     * 判断 传进来的 BigDecimal
     * 如果是 重量 保留三位小数 四舍五入
     * 如果是 厚度 保留三位小数 四舍五入
     * 如果是 宽度 保留一位小数 四舍五入
     * 如果是 长 保留整数 四舍五入
     *
     * @param value 值
     * @param conversionType 类型
     * @return {@link BigDecimal }
     **/
    public static BigDecimal conversionDecimal(BigDecimal value, String conversionType) {
        if (Objects.isNull(value) || StringUtils.isBlank(conversionType)) {
            return value;
        }
        switch (conversionType) {
            case Constants.ConversionType.WEIGHT:
            case Constants.ConversionType.THICKNESS:
                return value.setScale(3, RoundingMode.HALF_UP);
            case Constants.ConversionType.WIDTH:
                return value.setScale(1, RoundingMode.HALF_UP);
            case Constants.ConversionType.LENGTH:
                return value.setScale(0, RoundingMode.HALF_UP);
            default:
                throw new IllegalArgumentException("Unknown conversion type : " + conversionType);
        }
    }

    /**
     * 处理bigdecimal非空
     *
     * @param value
     * @return
     */
    public static BigDecimal getBigDecimalValue(BigDecimal value) {
        return value == null ? BigDecimal.ZERO : value;
    }
}