package nckd.jimin.jyyy.fi.common.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import kd.bos.algo.DataSet;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperateErrorInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.exception.KDBizException;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.org.OrgUnitServiceHelper;
import kd.bos.servicehelper.org.OrgViewType;
import nckd.jimin.jyyy.fi.common.constant.BillTypeConstants;


import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

public class CommonUtils {

    private static final SimpleDateFormat PERIOD_FORMAT = new SimpleDateFormat("yyyy-MM");



    public static String parsePeriod(Date date){
        return PERIOD_FORMAT.format(date);
    }

    public static Set getFiledFromDataSet(DataSet dt , String field){
        DataSet copy = dt.copy();
        Set datas = new HashSet();
        List<String> fileds = Arrays.stream(copy.getRowMeta().getFieldNames()).collect(Collectors.toList());
        while (copy.hasNext()){
            if(fileds.contains(field)){
                datas.add(copy.next().get(field));
            }
        }
        return datas;
    }
    public static String join(String... fileds){
        return String.join(".", fileds);
    }
    /**
     * 获取指定日期的开始时间（当天00:00:00）
     * @param date 指定日期
     * @return 当天的开始时间
     */
    public static Date getStartOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        // 将时分秒毫秒设置为0，确保是当天的开始
        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();
    }

    public static JSONArray transDataSetJson(DataSet dt , String... selectFiled){
        JSONArray jsonArray = new JSONArray();
        List<String> fileds = Arrays.stream(dt.getRowMeta().getFieldNames()).collect(Collectors.toList());
        while (dt.hasNext()){
            JSONObject obj = new JSONObject();
            for(String field : selectFiled){
                if(fileds.contains(field)){
                    obj.put(field,dt.next().get(field));
                }
            }
        }
        return jsonArray;
    }

    public static Set getFieldFormArray(JSONArray jsonArray , String filed){
        Set datas = new HashSet(jsonArray.size());
        for(int i = 0 ; i < jsonArray.size(); i++){
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            datas.add(jsonObject.get(filed));
        }

        return datas;
    }

    public static DataSet joinDataSetList(List<DataSet> dataSetList){
        DataSet dataSet = null;
        for(DataSet dt : dataSetList){
            if(dataSet == null){
                dataSet = dt;
            }else{
                dataSet = dt.union(dataSet);
            }
        }
        return dataSet;
    }

    /**
     * 获取操作错误信息
     * @param operationResult
     * @return
     */
    public static String getOperationResultErrorInfos(OperationResult operationResult){
        if(operationResult.isSuccess()){
            return StringUtils.EMPTY;
        }

        List<IOperateInfo> errorInfos = operationResult.getAllErrorOrValidateInfo();
        int size = errorInfos.size() + operationResult.getSuccessPkIds().size();
        if (size > 1) {
            StringBuilder stringBuilder = new StringBuilder();
            int i = 0;
            for(int len = errorInfos.size(); i < 5 && i < len; ++i) {
                stringBuilder.append((errorInfos.get(i)).getMessage());
            }
            return stringBuilder.toString();
        } else if (!errorInfos.isEmpty()) {
            OperateErrorInfo errorInfo = (OperateErrorInfo)errorInfos.get(0);
            String msg = errorInfo.getMessage() == null ? "" : errorInfo.getMessage();
            return msg;
        } else{
            String msg = operationResult.getMessage() == null ? "" : operationResult.getMessage();
            return msg;
        }
    }

    public static int getDateFeild(Date date , int filed){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(filed);
    }

    public static Date getFirstDayOfNextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        // 增加一个月
        calendar.add(Calendar.MONTH, 1);

        // 设置为该月的第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);

        // 将时分秒毫秒设置为0，确保是当天的开始
        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();
    }
    public static DynamicObject getUserByHrPersonId(Object hrPersonId){
        DynamicObject hrPersonInfo = QueryServiceHelper.queryOne("hrpi_person", "number", new QFilter("id", QCP.equals, hrPersonId).toArray());
        if(hrPersonInfo == null){
            return null;
        }

        String personNumber = hrPersonInfo.getString("number");
        if(StringUtils.isEmpty(personNumber)){
            return null;
        }
        return BusinessDataServiceHelper.loadSingleFromCache("bos_user", new QFilter("number",QCP.equals,personNumber).toArray());
    }

    public static Map<Long,Long> getUserByHrPersonId(List hrPersonIdList){
        DynamicObjectCollection hrPersonCol = QueryServiceHelper.query("hrpi_person", "number", new QFilter("id", QCP.in, hrPersonIdList).toArray());
        if(hrPersonCol == null || hrPersonCol.size() == 0){
            return null;
        }
        Map<Long, String> idNumberMap = hrPersonCol.stream().collect(Collectors.toMap(dyn -> dyn.getLong("id"), dyn -> dyn.getString("number"), (k1, k2) -> k1));
        DynamicObjectCollection userCol = QueryServiceHelper.query("bos_user", "id,number",new QFilter("number", QCP.in, idNumberMap.values()).toArray()   );
        Map<String, Long> userNumberMap = userCol.stream().collect(Collectors.toMap(dyn -> dyn.getString("number"), dyn -> dyn.getLong("id"), (k1, k2) -> k1));
        Map<Long, Long> idMap = new HashMap<>();
        for(Map.Entry<Long, String> entryRow : idNumberMap.entrySet()){
            Long personId = entryRow.getKey();
            String personNumber = entryRow.getValue();
            if(userNumberMap.containsKey(personNumber)){
                idMap.put(personId,userNumberMap.get(personNumber));
            }
        }
        return idMap;
    }

    public static Date parseDate(String date){
        try {
            return PERIOD_FORMAT.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null ;
    }

    public static int getDaysByWorkCalandar(Date startTime, Date endTime,DynamicObject org){
        // 获取组织下的工作日历
        DynamicObject workCalendar = getWorkCalandar(org.getLong("id"));
        List<Date> notWorkDayList = new ArrayList<>();
        if(workCalendar != null){
            notWorkDayList = QueryServiceHelper.query("bd_workcalendar", "dateentry.workdate", new QFilter[]{
                    new QFilter("dateentry.datetype", QCP.equals, "3"),
                    new QFilter("dateentry.workdate", QCP.large_equals, startTime),
                    new QFilter("dateentry.workdate", QCP.less_equals, endTime),
                    new QFilter("id", QCP.equals, workCalendar.getPkValue())
            }).stream().map(r -> r.getDate("dateentry.workdate")).collect(Collectors.toList());
        }
        startTime = CommonUtils.getStartOfDay(startTime);
        endTime = CommonUtils.getStartOfDay(endTime);
        // 计算开始日期和结束日期之间总天数，时间转成日期，然后相减
        long diffInMillis = endTime.getTime() - startTime.getTime();
        int totalDays = (int) (diffInMillis / (24 * 60 * 60 * 1000)) + 1;

        // 计算工作日天数（总天数减去非工作日天数）
        int workDays = totalDays - notWorkDayList.size();

        return workDays;
    }
    public static int getDays(Date startTime, Date endTime){
        if(startTime != null && endTime != null){
            long diffInMillis = endTime.getTime() - startTime.getTime();
            return (int) (diffInMillis / (24 * 60 * 60 * 1000));
        }
        return 0;
    }

    public static BigDecimal getBzAmount(DynamicObject applier){
        String userNumber = applier.getString("number");

        // 查询人员职级
        DynamicObject positionInfo = QueryServiceHelper.queryOne(BillTypeConstants.HRPI_EMPPOSORGREL, "position.id", new QFilter[]{
                new QFilter("businessstatus", QCP.equals, "1"),
                new QFilter("iscurrentversion", QCP.equals, "1"),
                new QFilter("datastatus", QCP.equals, "1"),
                new QFilter("isprimary", QCP.equals, "1"),
                new QFilter("person.number", QCP.equals, userNumber)
        });
        if(positionInfo != null){
            DynamicObject positionStandard = QueryServiceHelper.queryOne("nckd_checkstandard", "nckd_amount", new QFilter[]{
                    new QFilter("nckd_type", QCP.equals, "002"),
                    new QFilter("nckd_classify", QCP.equals, "002"),
                    new QFilter("nckd_multi_position.fbasedataid", QCP.equals, positionInfo.getLong("position.id"))
            });
            if(positionStandard != null){
                return positionStandard.getBigDecimal("nckd_amount");
            }
        }

        // 查询职级
        DynamicObject jobLeverInfo = QueryServiceHelper.queryOne(BillTypeConstants.HRPI_EMPJOBREL, "joblevel.id", new QFilter[]{
                new QFilter("businessstatus", QCP.equals, "1"),
                new QFilter("datastatus", QCP.equals, "1"),
                new QFilter("iscurrentversion", QCP.equals, "1"),
                new QFilter("person.number", QCP.equals, userNumber)
        });
        if(jobLeverInfo != null){
            DynamicObject jobLeverStandard = QueryServiceHelper.queryOne("nckd_checkstandard", "nckd_amount", new QFilter[]{
                    new QFilter("nckd_type", QCP.equals, "002"),
                    new QFilter("nckd_classify", QCP.equals, "001"),
                    new QFilter("nckd_multi_joblever.fbasedataid", QCP.equals, jobLeverInfo.getLong("joblevel.id"))
            });
            if(jobLeverStandard != null){
                return jobLeverStandard.getBigDecimal("nckd_amount");
            }
        }
        return BigDecimal.ZERO;
    }

    public static DynamicObject getWorkCalandar(Long orgId){
        DynamicObject workCalendar = QueryServiceHelper.queryOne("bd_workcalendar", "id", new QFilter("org", QCP.equals, orgId).toArray());
        if(workCalendar == null){
            Map<Long, Long> parentOrgMap = OrgUnitServiceHelper.getDirectSuperiorOrg(OrgViewType.Admin, Collections.singletonList(orgId));
            if(!parentOrgMap.containsKey(orgId)){
                return null;
            }else{
                return getWorkCalandar(parentOrgMap.get(orgId));
            }
        }
        return workCalendar;
    }

    public static BigDecimal add(BigDecimal... decimals) {
        return decimals == null ? BigDecimal.ZERO : (BigDecimal)Arrays.stream(decimals).reduce((a, b) -> {
            return nullToZero(a).add(nullToZero(b));
        }).orElse(BigDecimal.ZERO);
    }

    public static BigDecimal nullToZero(BigDecimal decimal) {
        return decimal == null ? BigDecimal.ZERO : decimal;
    }

}
