package cn.estsh.i3plus.ext.mes.apiservice.serviceimpl.busi.jx;

import cn.estsh.i3plus.ext.mes.api.base.IProdOrgExtService;
import cn.estsh.i3plus.ext.mes.api.base.bu.IBusiConfigService;
import cn.estsh.i3plus.ext.mes.api.base.jx.IJxTimeSegmentStatisticsService;
import cn.estsh.i3plus.ext.mes.api.busi.jx.IJxCenterWorkingBoardService;
import cn.estsh.i3plus.ext.mes.api.busi.jx.IJxMergeTimeSlotsService;
import cn.estsh.i3plus.ext.mes.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pojo.model.jx.JxCenterWorkingBoardBusiModel;
import cn.estsh.i3plus.ext.mes.pojo.model.jx.JxMergeTimeSlotsModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesShiftProdCenterRecordRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.SxWorkCellTaktCollectRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCell;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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

/**
 * @Author : wangjie
 * @CreateDate : 2022-02-15
 * @Modify:
 **/
@Slf4j
public class JxCenterWorkingBoardCenterThreeService extends JxCenterWorkingBoardCommonService implements IJxCenterWorkingBoardService {

    private IJxCenterWorkingBoardService proxyService0;

    private IJxCenterWorkingBoardService proxyService1;

    private IJxCenterWorkingBoardService proxyService;

    private IJxTimeSegmentStatisticsService timeSegmentStatisticsService;

    private IProdOrgExtService prodOrgExtService;

    private SxWorkCellTaktCollectRepository workCellTaktCollectRepository;

    private MesShiftProdCenterRecordRepository shiftProdCenterRecordRepository;

    private IBusiConfigService busiConfigService;

    private IJxMergeTimeSlotsService mergeTimeSlotsService;

    public JxCenterWorkingBoardCenterThreeService(IJxCenterWorkingBoardService proxyService0, IJxCenterWorkingBoardService proxyService1, IJxCenterWorkingBoardService proxyService) {
        this.proxyService0 = proxyService0;
        this.proxyService1 = proxyService1;
        this.proxyService = proxyService;
        this.timeSegmentStatisticsService = (IJxTimeSegmentStatisticsService) SpringContextsUtil.getBean("jxTimeSegmentStatisticsService");
        this.prodOrgExtService = (IProdOrgExtService) SpringContextsUtil.getBean("prodOrgExtService");
        this.workCellTaktCollectRepository = (SxWorkCellTaktCollectRepository) SpringContextsUtil.getBean("sxWorkCellTaktCollectRepository");
        this.shiftProdCenterRecordRepository = (MesShiftProdCenterRecordRepository) SpringContextsUtil.getBean("mesShiftProdCenterRecordRepository");
        this.busiConfigService = (IBusiConfigService) SpringContextsUtil.getBean("busiConfigService");
        this.mergeTimeSlotsService = (IJxMergeTimeSlotsService) SpringContextsUtil.getBean("jxMergeTimeSlotsService");
    }

    @Override
    public Map<String, Object> queryCenterWorkingBoardData(Map<String, Object> dataMap) {

        dataMap = proxyService0.queryCenterWorkingBoardData(dataMap);

        dataMap = proxyService1.queryCenterWorkingBoardData(dataMap);

        MesWorkCenterExt workCenterExtDb = (MesWorkCenterExt) dataMap.get(MesWorkCenterExt.class.getSimpleName());

        packProxyCondition(dataMap, workCenterExtDb);

        dataMap = proxyService.queryCenterWorkingBoardData(dataMap);

        List<MesWorkOrder> workOrderList = (List<MesWorkOrder>) dataMap.get(MesWorkOrder.class.getSimpleName());

        List<MesOutPutStatistics> outPutStatisticsList = (List<MesOutPutStatistics>) dataMap.get(MesOutPutStatistics.class.getSimpleName());

        List<MesOutPutStatisticsTimeSegment> outPutStatisticsTimeSegmentList = (List<MesOutPutStatisticsTimeSegment>) dataMap.get(MesOutPutStatisticsTimeSegment.class.getSimpleName());

        Optional<MesWorkOrder> curWorkOrder = getFirstWorkOrder(workOrderList, outPutStatisticsList, workCenterExtDb);

        List<MesOutPutStatistics> curOutPutStatisticsList = getFirstOutPutStatisticsList(outPutStatisticsList, curWorkOrder);

        dataMap.put("当前生产机种名", getCurProdPartNo(curOutPutStatisticsList, curWorkOrder));

        dataMap.put("当前计划台数", getQtyStr(getCurPlanQty(curOutPutStatisticsList, curWorkOrder, workCenterExtDb, dataMap)));

        Double completeQty = dataMap.containsKey(MesExtConstWords.COMPLET_QTY) ? (Double) dataMap.get(MesExtConstWords.COMPLET_QTY) : getOutPutStatisticsList2AmountQty(curOutPutStatisticsList);

        dataMap.put("当前实绩台数", getQtyStr(completeQty));

        dataMap.put("小时产量", getTimeSegmentStatistics(outPutStatisticsTimeSegmentList, workCenterExtDb));

        dataMap.put("工序平衡可视化", getWorkCellTaktStatistics(dataMap, workCenterExtDb, curWorkOrder, completeQty));

        return clearUselessData(dataMap);
    }

    @Override
    public Map<String, Object> clearUselessData(Map<String, Object> dataMap) {
        dataMap.remove(MesWorkCenterExt.class.getSimpleName());
        dataMap.remove(MesWorkOrder.class.getSimpleName());
        dataMap.remove(MesOutPutStatistics.class.getSimpleName());
        dataMap.remove(MesExtConstWords.COMPLET_QTY);
        dataMap.remove(MesExtConstWords.START_TIME);
        dataMap.remove(MesExtConstWords.END_TIME);
        dataMap.remove(MesExtConstWords.WORK_TIME);
        dataMap.remove(MesExtConstWords.SHIFT_CODE);
        dataMap.remove(MesExtConstWords.WORK_CENTER_CODE);
        dataMap.remove(MesExtConstWords.STANDARD_WORK);
        return dataMap;
    }

    private void packProxyCondition(Map<String, Object> dataMap, MesWorkCenterExt workCenterExtDb) {
        if (StringUtils.isEmpty(workCenterExtDb.getWorkTime()) || StringUtils.isEmpty(workCenterExtDb.getShiftCode())) return;
        dataMap.put(MesExtConstWords.START_TIME, TimeTool.timeCalc(TimeTool.stringParseToDate(workCenterExtDb.getWorkTime(), MesExtConstWords.DATE_FORMAT), Calendar.DATE, -1, MesExtConstWords.DATE_FORMAT));
        dataMap.put(MesExtConstWords.END_TIME, workCenterExtDb.getWorkTime());
        dataMap.put(MesExtConstWords.WORK_TIME, workCenterExtDb.getWorkTime());
        dataMap.put(MesExtConstWords.SHIFT_CODE, workCenterExtDb.getShiftCode());
        dataMap.put(MesExtConstWords.WORK_CENTER_CODE, workCenterExtDb.getWorkCenterCode());
    }

    private Optional<MesWorkOrder> getFirstWorkOrder(List<MesWorkOrder> workOrderList, List<MesOutPutStatistics> outPutStatisticsList, MesWorkCenterExt workCenterExtDb) {

        if (!CollectionUtils.isEmpty(outPutStatisticsList)) return CollectionUtils.isEmpty(workOrderList) ? null : workOrderList.stream().filter(o -> (null != o && o.getOrderNo().equals(outPutStatisticsList.get(0).getWorkOrderNo()))).findFirst();

        List<MesWorkOrder> workOrderList2Sort = getWorkOrderList2Sort(workOrderList, outPutStatisticsList, workCenterExtDb);

        return CollectionUtils.isEmpty(workOrderList2Sort) ? null : Optional.of(workOrderList2Sort.get(0));

    }

    private List<MesOutPutStatistics> getFirstOutPutStatisticsList(List<MesOutPutStatistics> outPutStatisticsList, Optional<MesWorkOrder> curWorkOrder) {
        String curWorkOrderNo = (null != curWorkOrder && curWorkOrder.isPresent()) ? curWorkOrder.get().getOrderNo() : (!CollectionUtils.isEmpty(outPutStatisticsList) ? outPutStatisticsList.get(0).getWorkOrderNo() : null);
        return (StringUtils.isEmpty(curWorkOrderNo) || CollectionUtils.isEmpty(outPutStatisticsList)) ? null : outPutStatisticsList.stream().filter(o -> (null != o && o.getWorkOrderNo().equals(curWorkOrderNo))).collect(Collectors.toList());
    }

    private Object getCurProdPartNo(List<MesOutPutStatistics> curOutPutStatisticsList, Optional<MesWorkOrder> curWorkOrder) {
        return !CollectionUtils.isEmpty(curOutPutStatisticsList) ? curOutPutStatisticsList.get(0).getPartNo() : ((null != curWorkOrder && curWorkOrder.isPresent()) ? curWorkOrder.get().getPartNo() : MesExtConstWords.EMPTY);
    }

    private Double getCurPlanQty(List<MesOutPutStatistics> curOutPutStatisticsList, Optional<MesWorkOrder> curWorkOrder, MesWorkCenterExt workCenterExtDb, Map<String, Object> dataMap) {
        return (null == curWorkOrder || !curWorkOrder.isPresent()) ? MesExtConstWords.ZERO :
                (curWorkOrder.get().getStartTime().contains(workCenterExtDb.getWorkTime()) ? curWorkOrder.get().getQty() :
                        MathOperation.add(MathOperation.sub(curWorkOrder.get().getQty(), curWorkOrder.get().getCompleteQty()), amountOutPutStatisticsQty(curOutPutStatisticsList, dataMap)));
    }

    private Double amountOutPutStatisticsQty(List<MesOutPutStatistics> outPutStatisticsList, Map<String, Object> dataMap) {
        Double qty = getOutPutStatisticsList2AmountQty(outPutStatisticsList);
        dataMap.put(MesExtConstWords.COMPLET_QTY, qty);
        return qty;
    }

    private JxCenterWorkingBoardBusiModel getTimeSegmentStatistics(List<MesOutPutStatisticsTimeSegment> outPutStatisticsTimeSegmentList, MesWorkCenterExt workCenterExtDb) {

        JxCenterWorkingBoardBusiModel psData = new JxCenterWorkingBoardBusiModel().title("小时产量");

        if (StringUtils.isEmpty(workCenterExtDb.getWorkTime()) || StringUtils.isEmpty(workCenterExtDb.getShiftCode())) return psData;

        String item = new StringJoiner(MesExtConstWords.AND).add("TIME_SEGMENT").add(workCenterExtDb.getWorkCenterCode()).add(workCenterExtDb.getShiftCode()).toString();
        String timeSegmentStatisticsList4Cached = (String) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), MesExtConstWords.ZERO_STR, item, null);
        List<MesTimeSegmentStatistics> timeSegmentStatisticsList = !StringUtils.isEmpty(timeSegmentStatisticsList4Cached) ? JSONObject.parseArray(timeSegmentStatisticsList4Cached, MesTimeSegmentStatistics.class) : execTimeSegmentStatistics(workCenterExtDb, item);
        timeSegmentStatisticsList = CollectionUtils.isEmpty(timeSegmentStatisticsList) ? null :
                timeSegmentStatisticsList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getStartTime()) && !StringUtils.isEmpty(o.getEndTime()))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(timeSegmentStatisticsList)) return psData;

        timeSegmentStatisticsList = timeSegmentStatisticsList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesTimeSegmentStatistics::getStartTime)).collect(Collectors.toList());

        Map<String, List<MesOutPutStatisticsTimeSegment>> statisticsMap = CollectionUtils.isEmpty(outPutStatisticsTimeSegmentList) ? null :
                outPutStatisticsTimeSegmentList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesOutPutStatisticsTimeSegment::getTimeSegmentCode));

        for (MesTimeSegmentStatistics timeSegmentStatistics : timeSegmentStatisticsList) {
            if (null == timeSegmentStatistics) continue;

            List<MesOutPutStatisticsTimeSegment> statisticsList = CollectionUtils.isEmpty(statisticsMap) ? null : statisticsMap.get(timeSegmentStatistics.getTimeSegmentCode());
            psData.addChartData(timeSegmentStatistics.getStartTime().substring(0, 5), getAmountPlanQty(timeSegmentStatistics, workCenterExtDb), getOutPutStatisticsTimeSegmentList2AmountQty(statisticsList));
        }

        return psData;

    }

    private List<MesTimeSegmentStatistics> execTimeSegmentStatistics(MesWorkCenterExt workCenterExtDb, String item) {
        List<MesTimeSegmentStatistics> timeSegmentStatisticsList = timeSegmentStatisticsService.getTimeSegmentStatisticsList(workCenterExtDb.getOrganizeCode(), workCenterExtDb.getWorkCenterCode(), workCenterExtDb.getShiftCode());
        if (!CollectionUtils.isEmpty(timeSegmentStatisticsList)) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr(), item, JSONObject.toJSONString(timeSegmentStatisticsList));
        return timeSegmentStatisticsList;
    }

    private Double getAmountPlanQty(MesTimeSegmentStatistics timeSegmentStatistics, MesWorkCenterExt workCenterExtDb) {
        if (StringUtils.isEmpty(workCenterExtDb.getWorkTakt()) || MathOperation.compareTo(workCenterExtDb.getWorkTakt(), new Double(0)) == 0) return new Double(0);
        return MathOperation.mul(new Double(getTimeLength(timeSegmentStatistics, workCenterExtDb.getWorkTime())), workCenterExtDb.getWorkTakt());
    }

    private Double getTimeLength(MesTimeSegmentStatistics timeSegmentStatistics, String workTime) {
        try {
            if (!StringUtils.isEmpty(timeSegmentStatistics.getTimeLength())) return new Double(timeSegmentStatistics.getTimeLength());
            return new Double(TimeTool.getSecoundsBetweenTime(2, appendWorkTime(timeSegmentStatistics.getStartTime(), workTime), appendWorkTime(timeSegmentStatistics.getEndTime(), workTime)));
        } catch (ParseException e) {
            return new Double(0);
        }
    }

    private String appendWorkTime(String hms, String workTime) {
        return new StringJoiner(MesExtConstWords.ONE_SPACE).add(workTime).add(hms).toString();
    }

    private Double getOutPutStatisticsTimeSegmentList2AmountQty(List<MesOutPutStatisticsTimeSegment> outPutStatisticsTimeSegmentList) {
        return CollectionUtils.isEmpty(outPutStatisticsTimeSegmentList) ? new Double(0) : outPutStatisticsTimeSegmentList.stream().filter(o -> null != o).mapToDouble(MesOutPutStatisticsTimeSegment::getQty).sum();
    }

    private JxCenterWorkingBoardBusiModel getWorkCellTaktStatistics(Map<String, Object> dataMap, MesWorkCenterExt workCenterExtDb, Optional<MesWorkOrder> curWorkOrder, Double completeQty) {

        JxCenterWorkingBoardBusiModel psData = new JxCenterWorkingBoardBusiModel().title("工序平衡可视化");

        List<MesWorkCell> workCellList = getWorkCellList(workCenterExtDb);

        if (CollectionUtils.isEmpty(workCellList)) return psData;

        String curTime = TimeTool.getNowTime(true);

        String lastHourTime = TimeTool.timeCalc(TimeTool.stringParseToDate(curTime, MesExtConstWords.DATETIME_FORMAT), Calendar.HOUR_OF_DAY, -1, MesExtConstWords.DATETIME_FORMAT);

        List<SxWorkCellTaktCollect> workCellTaktCollectList = getWorkCellTaktCollectList(workCenterExtDb, curTime, lastHourTime);

        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = getShiftProdCenterRecordList(workCenterExtDb, curTime, lastHourTime);

        MesBusiConfig limitCfg = getLimitCfg(workCenterExtDb);

        Map<String, List<SxWorkCellTaktCollect>> filterMap = getWorkCellTaktCollectList2Filter(workCellTaktCollectList, limitCfg);

        Map<String, String> partStandardWorkMap = (Map<String, String>) dataMap.get(MesExtConstWords.STANDARD_WORK);
        Double workStandard = (null != curWorkOrder && curWorkOrder.isPresent() && !CollectionUtils.isEmpty(partStandardWorkMap) && partStandardWorkMap.containsKey(curWorkOrder.get().getPartNo())) ? Double.parseDouble(partStandardWorkMap.get(curWorkOrder.get().getPartNo())) : new Double(0);

        for (MesWorkCell workCell : workCellList) {
            if (null == workCell) continue;
            List<SxWorkCellTaktCollect> resultList = CollectionUtils.isEmpty(filterMap) ? null : filterMap.get(workCell.getWorkCellCode());
            psData.addChartData(workCell.getSeq().toString(), getCellRealTakt(resultList), getRealTakt(shiftProdCenterRecordList, completeQty, curTime, lastHourTime), getStandardTakt(workStandard, workCenterExtDb));
        }

        return psData;
    }

    private List<MesWorkCell> getWorkCellList(MesWorkCenterExt workCenterExtDb) {
        String item = new StringJoiner(MesExtConstWords.AND).add("CELLS").add(workCenterExtDb.getWorkCenterCode()).toString();
        String workCellList4Cached = (String) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), MesExtConstWords.ZERO_STR, item, null);
        List<MesWorkCell> workCellList = !StringUtils.isEmpty(workCellList4Cached) ? JSONObject.parseArray(workCellList4Cached, MesWorkCell.class) : execWorkCellList(workCenterExtDb, item);
        return CollectionUtils.isEmpty(workCellList) ? null : workCellList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getSeq()))).sorted(Comparator.comparing(MesWorkCell::getSeq)).collect(Collectors.toList());
    }

    private List<MesWorkCell> execWorkCellList(MesWorkCenterExt workCenterExtDb, String item) {
        List<MesWorkCell> workCellList = prodOrgExtService.getWorkCellListByCenter(workCenterExtDb.getOrganizeCode(), workCenterExtDb.getWorkCenterCode());
        if (!CollectionUtils.isEmpty(workCellList)) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr(), item, JSONObject.toJSONString(workCellList));
        return workCellList;
    }

    private List<SxWorkCellTaktCollect> getWorkCellTaktCollectList(MesWorkCenterExt workCenterExtDb, String curTime, String lastHourTime) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(workCenterExtDb.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(workCenterExtDb.getWorkCenterCode(), MesExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.timeBuilder(lastHourTime, curTime, MesExtConstWords.CREATE_DATE_TIME, true, true, packBean);
        return workCellTaktCollectRepository.findByHqlWhere(packBean);
    }

    private MesBusiConfig getLimitCfg(MesWorkCenterExt workCenterExtDb) {
        String limitCfg4Cached = (String) execCachedCenterWorkingBoardData(workCenterExtDb.getOrganizeCode(), MesExtConstWords.ZERO_STR, MesExtConstWords.SX_WORK_CELL_TAKT_LIMIT_CFG, null);
        return !StringUtils.isEmpty(limitCfg4Cached) ? JSONObject.parseObject(limitCfg4Cached, MesBusiConfig.class) : execLimitCfg(workCenterExtDb.getOrganizeCode());
    }

    private MesBusiConfig execLimitCfg(String organizeCode) {
        MesBusiConfig limitCfg = busiConfigService.getBusiConfigByCfgCode(organizeCode, MesExtConstWords.SX_WORK_CELL_TAKT_LIMIT_CFG);
        if (null != limitCfg) execCachedCenterWorkingBoardData(organizeCode, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr(), MesExtConstWords.SX_WORK_CELL_TAKT_LIMIT_CFG, JSONObject.toJSONString(limitCfg));
        return limitCfg;
    }

    private Map<String, List<SxWorkCellTaktCollect>> getWorkCellTaktCollectList2Filter(List<SxWorkCellTaktCollect> workCellTaktCollectList, MesBusiConfig limitCfg) {
        if (CollectionUtils.isEmpty(workCellTaktCollectList)) return null;
        workCellTaktCollectList = workCellTaktCollectList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTakt()) && workCellTaktCollectCompareToCfg(o, limitCfg))).collect(Collectors.toList());
        return workCellTaktCollectList.stream().filter(o -> null != o).collect(Collectors.groupingBy(SxWorkCellTaktCollect::getWorkCellCode));
    }

    private Boolean workCellTaktCollectCompareToCfg(SxWorkCellTaktCollect workCellTaktCollect, MesBusiConfig limitCfg) {
        if (null == limitCfg || (StringUtils.isEmpty(limitCfg.getCfgValue()) || !limitCfg.getCfgValue().contains(MesExtConstWords.COMMA))) return true;
        String[] limitArr = limitCfg.getCfgValue().split(MesExtConstWords.COMMA);
        if (limitArr.length != 2) return true;
        if (!StringUtils.isEmpty(limitArr[0]) && MathOperation.compareTo(Double.parseDouble(workCellTaktCollect.getWorkTakt()), Double.parseDouble(limitArr[0])) < 0) return false;
        if (!StringUtils.isEmpty(limitArr[1]) && MathOperation.compareTo(Double.parseDouble(workCellTaktCollect.getWorkTakt()), Double.parseDouble(limitArr[1])) > 0) return false;
        return true;
    }

    private BigDecimal getCellRealTakt(List<SxWorkCellTaktCollect> resultList) {
        if (CollectionUtils.isEmpty(resultList)) return format1RounHalfUp(new Double(0));
        return format1RounHalfUp(MathOperation.div(resultList.stream().filter(o -> null != o).mapToDouble(o -> Double.parseDouble(o.getWorkTakt())).sum(), new Double(resultList.size())));
    }

    private BigDecimal getStandardTakt(Double workStandard, MesWorkCenterExt workCenterExtDb) {
        if (MathOperation.compareTo(workStandard, new Double(0)) == 0 || (StringUtils.isEmpty(workCenterExtDb.getWorkerQty()) || MathOperation.compareTo(workCenterExtDb.getWorkerQty(), new Double(0)) == 0)) return format1RounHalfUp(new Double(0));
        return format1RounHalfUp(MathOperation.div(MathOperation.mul(workStandard, new Double(60)), workCenterExtDb.getWorkerQty()));
    }

    private List<MesShiftProdCenterRecord> getShiftProdCenterRecordList(MesWorkCenterExt workCenterExtDb, String curTime, String lastHourTime) {
        List<MesShiftProdCenterRecord> shiftProdCenterRecordList = new ArrayList<>();
        shiftProdCenterRecordList.addAll(getShiftProdCenterRecordListByTime(workCenterExtDb, lastHourTime, curTime, MesExtConstWords.START_TIME));
        shiftProdCenterRecordList.addAll(getShiftProdCenterRecordListByTime(workCenterExtDb, lastHourTime, curTime, MesExtConstWords.END_TIME));
        return CollectionUtils.isEmpty(shiftProdCenterRecordList) ? null :
                shiftProdCenterRecordList.stream().filter(o -> null != o).distinct().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MesShiftProdCenterRecord::getId))), ArrayList::new));
    }

    private List<MesShiftProdCenterRecord> getShiftProdCenterRecordListByTime(MesWorkCenterExt workCenterExtDb, String lastHourTime, String curTime, String fieldName) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(workCenterExtDb.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(workCenterExtDb.getWorkCenterCode(), MesExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.timeBuilder(lastHourTime, curTime, fieldName, true, false, packBean);
        return shiftProdCenterRecordRepository.findByHqlWhere(packBean);
    }

    private BigDecimal getRealTakt(List<MesShiftProdCenterRecord> shiftProdCenterRecordList, Double completeQty, String curTime, String lastHourTime) {
        if (MathOperation.compareTo(completeQty, new Double(0)) == 0) return format1RounHalfUp(new Double(0));
        return format1RounHalfUp(MathOperation.div(MathOperation.mul(MathOperation.sub(new Double(60), getStopTime(shiftProdCenterRecordList, curTime, lastHourTime)), new Double(60)), completeQty));
    }

    private Double getStopTime(List<MesShiftProdCenterRecord> shiftProdCenterRecordList, String curTime, String lastHourTime) {
        if (CollectionUtils.isEmpty(shiftProdCenterRecordList)) return new Double(0);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(MesExtConstWords.DATETIME_FORMAT);
        List<JxMergeTimeSlotsModel> timeSlots = new ArrayList<>();
        for (MesShiftProdCenterRecord shiftProdCenterRecord : shiftProdCenterRecordList) {
            if (null == shiftProdCenterRecord) continue;
            timeSlots.add(new JxMergeTimeSlotsModel().convertTime(compareToTimeByFlag(shiftProdCenterRecord.getStartTime(), lastHourTime, true), compareToTimeByFlag(shiftProdCenterRecord.getEndTime(), curTime, false), simpleDateFormat));
        }
        timeSlots = mergeTimeSlotsService.mergeTimeSlots(timeSlots);
        return CollectionUtils.isEmpty(timeSlots) ? new Double(0) :
                timeSlots.stream().filter(o -> null != o).mapToDouble(o -> (MathOperation.div((double)(o.getEndDate().getTime() - o.getStartDate().getTime()), new Double(60000)))).sum();
    }

    private String compareToTimeByFlag(String time, String curTime, boolean flag) {
        if (flag ? time.compareTo(curTime) > 0 : time.compareTo(curTime) < 0) return curTime;
        else return time;
    }

}
