package yem.wmc.ydn.utils;

import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
import kd.bos.servicehelper.workflow.MessageCenterServiceHelper;
import kd.bos.workflow.engine.msg.info.MessageInfo;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;

/**
 * @Description: 常用工具类
 * @author SimonFan
 * @date 2021年12月20日上午10:13:40
 * @version V1.0
 */
public class GeneralUtils {

    /**
     * 消息中心-发送消息
     *
     * @param receiverslist
     *            //接收人内码集合
     * @param type
     *            //消息平台-消息类型 ：可自行设置
     * @param title
     *            //标题
     * @param msg
     *            //详细内容
     * @param tag
     *            //业务标签
     * @return
     */
    public static long sendMessage(final List<Long> receiverslist, String type, String title, String msg, String tag) {
        RequestContext requestContext = RequestContext.get();
        String userName = requestContext.getUserName();
        MessageInfo message = new MessageInfo();
        message.setUserIds(receiverslist);
        message.setSenderName(userName);
        message.setType(type);
        message.setTitle(title);
        message.setContent(msg);
        message.setTag(tag);
        return MessageCenterServiceHelper.sendMessage(message);
    }

    /**
     * 根据物料、计量单位、基本单位获取转换率
     *
     * @param material
     * @param srcUnit
     * @param desUnit
     * @return
     */
    public static BigDecimal getUnitRate(final DynamicObject material, final DynamicObject srcUnit,
                                         final DynamicObject desUnit) {
        BigDecimal unitRate = BigDecimal.ZERO;
        if (material == null || srcUnit == null || desUnit == null) {
            return unitRate;
        }
        final Long materialId = material.getLong("id");
        final Long srcUnitId = srcUnit.getLong("id");
        final Long desUnitId = desUnit.getLong("id");
        if (srcUnitId.equals(desUnitId)) {
            return BigDecimal.ONE;
        } else {
            final DynamicObject muConv = BaseDataServiceHelper.getMUConv(materialId, srcUnitId, desUnitId);
            if (muConv != null && muConv.getInt("numerator") != 0) {
                unitRate = new BigDecimal(muConv.getInt("numerator"))
                        .divide(new BigDecimal(muConv.getInt("denominator")), 10, 4);
            }
        }
        if (unitRate == null) {
            unitRate = BigDecimal.ZERO;
        }
        return unitRate;
    }

    /**
     * 获取汇率
     *
     * @param exchangeRateTable
     * @param sourceCurrency
     * @param targetCurrency
     * @param org
     * @param date
     * @return
     */
    public static BigDecimal getExchangeRate(final DynamicObject exchangeRateTable, final DynamicObject sourceCurrency,
                                             final DynamicObject targetCurrency, final DynamicObject org, Date date) {
        BigDecimal exchangeRate = BigDecimal.ONE;
        if (date == null) {
            date = new Date();
        }
        if (sourceCurrency == null || targetCurrency == null) {
            return exchangeRate;
        }
        final Long sourceCurrencyId = sourceCurrency.getLong("id");
        final Long targetCurrencyId = targetCurrency.getLong("id");
        if (sourceCurrencyId.equals(targetCurrencyId)) {
            return exchangeRate;
        }
        // 汇率表为空时 取 应收初始化 汇率类型；不为空是取单据参数
        if (exchangeRateTable == null) {
            if (getExrateTable(org) != null) {
                Long exchangeRateTableId = getExrateTable(org).getLong("id");
                exchangeRate = BaseDataServiceHelper.getExchangeRate(exchangeRateTableId, sourceCurrencyId,
                        targetCurrencyId, date);
            }
        } else {
            Long exchangeRateTableId = exchangeRateTable.getLong("id");
            exchangeRate = BaseDataServiceHelper.getExchangeRate(exchangeRateTableId, sourceCurrencyId,
                    targetCurrencyId, date);
        }
        if (exchangeRate == null) {
            exchangeRate = BigDecimal.ONE;
        }
        return exchangeRate;
    }

    /**
     * 获取汇率类型表名
     *
     * @param orgId
     * @return
     */
    public static DynamicObject getExrateTable(final DynamicObject org) {
        if (org == null) {
            return null;
        }
        final DynamicObject systemStatusCtrol = getSystemStatusCtrol(org);
        if (systemStatusCtrol == null) {
            return null;
        }
        return systemStatusCtrol.getDynamicObject("exratetable");
    }

    /**
     * 获取系统状态控制
     *
     * @param orgId
     * @return
     */
    private static DynamicObject getSystemStatusCtrol(final DynamicObject org) {
        final QFilter[] filters = { new QFilter("org", "=", org.getLong("id")) };
        final DynamicObjectCollection ArInitColl = QueryServiceHelper.query("ar_init", "id", filters);
        if (ArInitColl.size() == 0) {
            return null;
        }
        final DynamicObject ArInit = BusinessDataServiceHelper.loadSingle(ArInitColl.get(0).getLong("id"), "ar_init");
        return ArInit;
    }

    /**
     * 判断对象是否为空
     *
     * @param o
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static boolean isNull(final Object o) {
        return o == null || (o instanceof String && ((String) o).length() == 0)
                || (o instanceof StringBuffer && ((StringBuffer) o).length() == 0)
                || (o instanceof List && ((List) o).size() == 0)
                || (o instanceof Collection && ((Collection) o).size() == 0)
                || (o instanceof Object[] && ((Object[]) o).length == 0) || (o instanceof Map && ((Map) o).size() == 0);
    }

    /***
     * BigDecimal加法运算
     *
     * @param BigDecimal
     * @param BigDecimal
     * @param scale
     *            精度
     * @return
     */
    public static BigDecimal addBigDecimal(BigDecimal aVal, BigDecimal bVal, int scale) {

        if (aVal == null)
            aVal = BigDecimal.ZERO;

        if (bVal == null)
            bVal = BigDecimal.ZERO;

        return aVal.add(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * BigDecimal减法运算
     *
     * @param BigDecimal
     * @param BigDecimal
     * @param scale
     *            精度
     * @return
     */
    public static BigDecimal subtractBigDecimal(BigDecimal aVal, BigDecimal bVal, int scale) {

        if (aVal == null)
            aVal = BigDecimal.ZERO;

        if (bVal == null)
            bVal = BigDecimal.ZERO;

        return aVal.subtract(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * BigDecimal乘法运算
     *
     * @param BigDecimal
     * @param BigDecimal
     * @param scale
     *            精度
     * @return
     */
    public static BigDecimal multiplyBigDecimal(BigDecimal aVal, BigDecimal bVal, int scale) {

        if (aVal == null)
            aVal = BigDecimal.ZERO;

        if (bVal == null)
            bVal = BigDecimal.ZERO;

        return aVal.multiply(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /***
     * BigDecimal除法运算
     *
     * @param BigDecimal
     * @param BigDecimal
     * @param scale
     *            精度
     * @return
     */
    public static BigDecimal divideBigDecimal(BigDecimal aVal, BigDecimal bVal, int scale) {

        if (aVal == null)
            aVal = BigDecimal.ZERO;

        if (bVal == null)
            return BigDecimal.ZERO;

        if (bVal.compareTo(BigDecimal.ZERO) == 0)
            return BigDecimal.ZERO;

        return aVal.divide(bVal, scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 指定字符，截取字符串中最后一个该字符之前或之后的部分
     *
     * @param str
     * @param symbol
     *            指定字符
     * @return
     */
    public static String substringAfterLast(String str, String symbol) {
        return org.apache.commons.lang.StringUtils.substringAfterLast(str, symbol);
    }

    public static String substringBeforeLast(String str, String symbol) {
        return org.apache.commons.lang.StringUtils.substringBeforeLast(str, symbol);
    }

    /**
     * Integer转为String固定位数，不足补零
     *
     * @param seq
     * @param format
     *            //常用："%04d"，0代表前面要补的字符（不加为空格），4代表字符串长度，d表示参数为整数类型
     * @return
     */
    public static String formatInteger(String format, Integer seq) {
        return String.format(format, seq);
    }

    /**
     * 日期格式化
     *
     * @param date
     * @param format
     *            //常用："yyyy-MM-dd","yyyy-MM-dd HH:mm:ss","yyyyMMdd"
     * @return
     */
    public static String formatDate(Date date, String format) {
        SimpleDateFormat simpleFormat = new SimpleDateFormat(format);
        return simpleFormat.format(date);
    }

    /***
     * 计算用时天数（向下取整）
     *
     * @param begin
     * @param end
     * @return
     */
    public static int countDays(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / (1000 * 60 * 60 * 24));
    }

    /***
     * 计算用时小时数（向下取整）
     *
     * @param begin
     * @param end
     * @return
     */
    public static int countHours(Date begin, Date end) {
        return (int) ((end.getTime() - begin.getTime()) / (1000 * 60 * 60));
    }

    /**
     * 计算实际用时天数（注：1月1日 23:59:59 - 1月2日 00:00:01 算两天）
     *
     * @param begin
     * @param end
     * @return
     */
    public static int countActualDays(Date begin, Date end) {
        LocalDate start = begin.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate over = end.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return (int) (over.toEpochDay() - start.toEpochDay() + 1);
    }

    /**
     * 获取指定日期添加/减去指定天数后的日期
     *
     * @param date
     * @param days
     *            负参为减
     * @return
     */
    public static Date addDays(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }

    /**
     * 将日期的 时、分、秒、毫秒域 清零
     *
     * @param date
     * @return
     */
    public static Date cleanDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 随机生成颜色
     *
     * @param count
     * @return
     */
    public static List<String> getRandColors(Integer count) {
        List<String> colorCodes = new ArrayList<String>();
        String r, g, b;
        for (int i = 0; i < count; i++) {
            Random random = new Random();
            r = Integer.toHexString(random.nextInt(256)).toUpperCase();
            g = Integer.toHexString(random.nextInt(256)).toUpperCase();
            b = Integer.toHexString(random.nextInt(256)).toUpperCase();

            r = r.length() == 1 ? "0" + r : r;
            g = g.length() == 1 ? "0" + g : g;
            b = b.length() == 1 ? "0" + b : b;
            colorCodes.add("#" + r + g + b);
        }
        return colorCodes;
    }

    /**
     * 从数组中随机取出N个不重复的元素
     *
     * @param array
     * @param n
     * @return
     */
    public static Object[] getRandomsInArray(Object[] array, int n) {
        if (array == null || array.length <= n) {
            return array;
        } else {
            List<Object> news = new ArrayList<>();
            List<Object> olds = new ArrayList<>();
            Collections.addAll(olds, array);
            while (news.size() < n) {
                int random = (int) (Math.random() * olds.size());
                news.add(olds.get(random));
                olds.remove(random);
            }
            return news.toArray(new Object[0]);
        }
    }
}