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

import cn.estsh.i3plus.ext.mes.api.base.bu.IBusiConfigService;
import cn.estsh.i3plus.ext.mes.api.base.bu3.ISxPartCategoryPlanRateService;
import cn.estsh.i3plus.ext.mes.api.busi.bu3.ISxNonWorkingTimeAnalysisService;
import cn.estsh.i3plus.ext.mes.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxEChartsReportCommonDataModel;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxNonWorkingTimeAnalysisModel;
import cn.estsh.i3plus.ext.mes.pojo.model.bu3.SxShiftProdCenterRecordStatisticsModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesProdDataToStatisticsShiftProdRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesShiftProdCenterRecordRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesShiftProdRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesWorkCenterExtRepository;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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

/**
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
@Service
public class SxNonWorkingTimeAnalysisService implements ISxNonWorkingTimeAnalysisService {

    @Autowired
    private IBusiConfigService busiConfigService;

    @Autowired
    private MesWorkCenterExtRepository workCenterExtRepository;

    @Autowired
    private MesShiftProdRepository shiftProdRepository;

    @Autowired
    private MesShiftProdCenterRecordRepository shiftProdCenterRecordRepository;

    @Autowired
    private MesProdDataToStatisticsShiftProdRepository prodDataToStatisticsShiftProdRepository;

    @Autowired
    private ISxPartCategoryPlanRateService partCategoryPlanRateService;

    @Override
    public SxNonWorkingTimeAnalysisModel queryNonWorkingTimeAnalysis(SxNonWorkingTimeAnalysisModel data) {

        sxYearFlag(data);

        calcDate(data);

        List<MesWorkCenterExt> workCenterExtList = getWorkCenterExtList(data);

        Map<String, MesWorkCenterExt> centerMap = getCenterMap(workCenterExtList);

        if (CollectionUtils.isEmpty(centerMap)) return data;

        Map<String, List<MesShiftProd>> shiftProdMap = getShiftProdMap(data.getOrganizeCode());

        List<SxShiftProdCenterRecordStatisticsModel> yearDataList = getYearDataList(data, centerMap, shiftProdMap);

        List<SxShiftProdCenterRecordStatisticsModel> monthDataList = getMonthDataList(data, yearDataList, centerMap, shiftProdMap);

        title(data);

        if (CollectionUtils.isEmpty(yearDataList) && CollectionUtils.isEmpty(monthDataList)) return data;

        if (StringUtils.isEmpty(data.getPlanRate())) data.setPlanRate(getPlanRateByCareerCode(data, workCenterExtList));

        handleMonthDataList(data, monthDataList);

        handleYearDataList(data, yearDataList);

        return data;
    }

    private void sxYearFlag(SxEChartsReportCommonDataModel data) {
        MesBusiConfig busiConfig = busiConfigService.getBusiConfigByCfgCode(data.getOrganizeCode(), MesExtConstWords.SX_REPORT_IS_PANASONIC_YEAR);
        if (null != busiConfig) data.setSxYearFlag(true);
    }

    private void title(SxNonWorkingTimeAnalysisModel data) {
        String[] time = data.getWorkTime().split(MesExtConstWords.E_LINE);
        data.title(time[0] + "年" + Integer.valueOf(time[1]) + "月" + data.getCategoryName() + "非作业时间");
    }

    private void calcDate(SxNonWorkingTimeAnalysisModel data) {
        if (!data.getSxYearFlag()) {
            data.setWorkTimeStart(data.getYear() + "-01");
            data.setWorkTimeEnd(data.getYear() + "-12");
        } else {
            data.setWorkTimeStart(data.getYear() + "-04");
            data.setWorkTimeEnd(data.getYear() + 1 + "-03");
        }

        data.setCurMonth(TimeTool.getToday().substring(0, 7));

        if (data.getCurMonth().compareTo(data.getWorkTimeStart()) <= 0) {
            data.setWorkTimeYmdStart(data.getWorkTimeStart() + MesExtConstWords.DATE_DD_01);
            data.setWorkTimeYmdEnd(data.getWorkTimeEnd() + "-31");
        } else if (data.getCurMonth().compareTo(data.getWorkTimeEnd()) > 0) {
            data.setWorkTimeYmStart(data.getWorkTimeStart());
            data.setWorkTimeYmEnd(data.getWorkTimeEnd());
        } else {
            data.setWorkTimeYmStart(data.getWorkTimeStart());
            data.setWorkTimeYmEnd(TimeTool.timeCalc(TimeTool.stringParseToDate(data.getCurMonth(), MesExtConstWords.DATE_FORMAT_YM), Calendar.MONTH, -1, MesExtConstWords.DATE_FORMAT_YM));
            data.setWorkTimeYmdStart(data.getCurMonth() + MesExtConstWords.DATE_DD_01);
            data.setWorkTimeYmdEnd(data.getWorkTimeEnd() + "-31");
        }
    }

    private List<MesWorkCenterExt> getWorkCenterExtList(SxNonWorkingTimeAnalysisModel data) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(data.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(data.getIsDont(), MesExtConstWords.IS_DONT, packBean);
        DdlPreparedPack.getStringEqualPack(data.getDontClass(), MesExtConstWords.DONT_CLASS, packBean);
        List<MesWorkCenterExt> workCenterExtList = workCenterExtRepository.findByHqlWhere(packBean);
        if (StringUtils.isEmpty(data.getWorkCenterCodeArr())) return workCenterExtList;
        List<String> workCenterCodeList = Arrays.asList(data.getWorkCenterCodeArr().split(MesExtConstWords.COMMA));
        return CollectionUtils.isEmpty(workCenterExtList) ? null :
                workCenterExtList.stream().filter(o -> (null != o && workCenterCodeList.contains(o.getWorkCenterCode()))).collect(Collectors.toList());
    }

    private Map<String, MesWorkCenterExt> getCenterMap(List<MesWorkCenterExt> workCenterExtList) {
        return CollectionUtils.isEmpty(workCenterExtList) ? null :
                workCenterExtList.stream().filter(o -> null != o).collect(Collectors.toMap(MesWorkCenterExt::getWorkCenterCode, o -> o));
    }

    private Map<String, List<MesShiftProd>> getShiftProdMap(String organizeCode) {
        List<MesShiftProd> shiftProdList = shiftProdRepository.findByProperty(
                new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_DELETED, MesExtConstWords.IS_VALID},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue()});
        return CollectionUtils.isEmpty(shiftProdList) ? null :
                shiftProdList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getProdCode()) && !StringUtils.isEmpty(o.getProdType())))
                        .collect(Collectors.groupingBy(o -> new StringJoiner(MesExtConstWords.AND).add(o.getProdType().toString()).add(o.getProdCode()).toString()));
    }

    private String getPlanRateByCareerCode(SxNonWorkingTimeAnalysisModel data, List<MesWorkCenterExt> workCenterExtList) {
        if (StringUtils.isEmpty(data.getCareerCode())) return MesExtConstWords.ZERO_STR;
        List<String> categoryCodeList = workCenterExtList.stream().filter(o -> (null != o &&
                !StringUtils.isEmpty(o.getCareerCode()) && !StringUtils.isEmpty(o.getCategoryCode()) && o.getCareerCode().equals(data.getCareerCode()))).map(MesWorkCenterExt::getCategoryCode).collect(Collectors.toList());
        categoryCodeList = CollectionUtils.isEmpty(categoryCodeList) ? categoryCodeList : categoryCodeList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(categoryCodeList)) return MesExtConstWords.ZERO_STR;
        List<MesPartCategoryPlanRate> partCategoryPlanRateList = partCategoryPlanRateService.getPartCategoryPlanRateList(data.getOrganizeCode());
        List<String> finalCategoryCodeList = categoryCodeList;
        partCategoryPlanRateList = CollectionUtils.isEmpty(partCategoryPlanRateList) ? null :
                partCategoryPlanRateList.stream().filter(o -> (null != o && finalCategoryCodeList.contains(o.getCategoryCode()) && !StringUtils.isEmpty(o.getPlanRate()))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(partCategoryPlanRateList)) return MesExtConstWords.ZERO_STR;
        Double planRateAmount = partCategoryPlanRateList.stream().filter(o -> null != o).mapToDouble(o -> Double.valueOf(o.getPlanRate())).sum();
        return String.valueOf(MathOperation.div(planRateAmount, new Double(partCategoryPlanRateList.size())));
    }

    private String getProdName(Map<String, List<MesShiftProd>> shiftProdMap, Integer prodType, String prodCode) {
        String key = new StringJoiner(MesExtConstWords.AND).add(prodType.toString()).add(prodCode).toString();
        return (!CollectionUtils.isEmpty(shiftProdMap) && shiftProdMap.containsKey(key)) ? shiftProdMap.get(key).get(0).getProdName() : null;
    }

    private List<SxShiftProdCenterRecordStatisticsModel> getYearDataList(SxNonWorkingTimeAnalysisModel data, Map<String, MesWorkCenterExt> centerMap, Map<String, List<MesShiftProd>> shiftProdMap) {
        List<SxShiftProdCenterRecordStatisticsModel> yearDataList = new ArrayList<>();
        if (!StringUtils.isEmpty(data.getWorkTimeYmdStart())) {
            List<SxShiftProdCenterRecordStatisticsModel> resultList = getShiftProdCenterRecordList(data, data.getWorkTimeYmdStart(), data.getWorkTimeYmdEnd(), centerMap, shiftProdMap);
            if (!CollectionUtils.isEmpty(resultList)) yearDataList.addAll(resultList);
        }
        if (!StringUtils.isEmpty(data.getWorkTimeYmStart())) {
            List<SxShiftProdCenterRecordStatisticsModel> resultList = getShiftProdCenterRecordStatisticsList(data, data.getWorkTimeYmStart(), data.getWorkTimeYmEnd(), centerMap, shiftProdMap);
            if (!CollectionUtils.isEmpty(resultList)) yearDataList.addAll(resultList);
        }
        yearDataList = CollectionUtils.isEmpty(yearDataList) ? yearDataList :
                yearDataList.stream().filter(o -> (null != o && centerMap.containsKey(o.getWorkCenterCode()))).collect(Collectors.toList());
        return yearDataList;
    }

    private List<SxShiftProdCenterRecordStatisticsModel> getShiftProdCenterRecordList(SxNonWorkingTimeAnalysisModel data, String workTimeStart, String workTimeEnd, Map<String, MesWorkCenterExt> centerMap, Map<String, List<MesShiftProd>> shiftProdMap) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(data.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(data.getCategoryCode(), MesExtConstWords.CATEGORY_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(data.getCareerCode(), MesExtConstWords.CAREER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(data.getShiftCode(), MesExtConstWords.SHIFT_CODE, packBean);

        if (!StringUtils.isEmpty(workTimeEnd)) DdlPreparedPack.timeBuilder(workTimeStart, workTimeEnd, MesExtConstWords.WORK_TIME, packBean, false);
        else DdlPreparedPack.timeBuilder(workTimeStart,
                TimeTool.timeCalc(TimeTool.stringParseToDate(data.getWorkTime(), MesExtConstWords.DATE_FORMAT_YM), Calendar.MONTH, 1, MesExtConstWords.DATE_FORMAT_YM) + MesExtConstWords.DATE_DD_01,
                MesExtConstWords.WORK_TIME, true, false, packBean);

        List<MesShiftProdCenterRecord> shiftProdCenterRecordList =  shiftProdCenterRecordRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(shiftProdCenterRecordList)) return null;
        List<SxShiftProdCenterRecordStatisticsModel> resultList = new ArrayList<>();
        for (MesShiftProdCenterRecord item : shiftProdCenterRecordList) {
            if (null == item || StringUtils.isEmpty(item.getProdType())) continue;
            SxShiftProdCenterRecordStatisticsModel result = new SxShiftProdCenterRecordStatisticsModel();
            BeanUtils.copyProperties(item, result);
            result.setWorkTime(result.getWorkTime().substring(0, 7));
            result.setProdName(getProdName(shiftProdMap, result.getProdType(), result.getProdCode()));
            packCenterInfo(centerMap, result);
            try {
                result.setStatistics(MathOperation.mul(new Double(TimeTool.getSecoundsBetweenTime(2, item.getStartTime(), item.getEndTime())), item.getWorkerQty()));
            } catch (ParseException e) {
                result.setStatistics(new Double(0));
            }
            resultList.add(result);
        }
        return resultList;
    }

    private List<SxShiftProdCenterRecordStatisticsModel> getShiftProdCenterRecordStatisticsList(SxNonWorkingTimeAnalysisModel data, String workTimeStart, String workTimeEnd, Map<String, MesWorkCenterExt> centerMap, Map<String, List<MesShiftProd>> shiftProdMap) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(data.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(data.getCategoryCode(), MesExtConstWords.CATEGORY_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(data.getCareerCode(), MesExtConstWords.CAREER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(data.getShiftCode(), MesExtConstWords.SHIFT_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(MesExtConstWords.MONTH, MesExtConstWords.DATA_TYPE, packBean);
        DdlPreparedPack.getStringEqualPack(MesExtEnumUtil.JOB_STATISTICS_PROD_DATA_KEY.SHIFT_PROD_MONTH_KEY.getValue(), MesExtConstWords.DATA_KEY, packBean);

        if (!StringUtils.isEmpty(workTimeEnd)) DdlPreparedPack.timeBuilder(workTimeStart, workTimeEnd, MesExtConstWords.WORK_TIME, packBean, false);
        else DdlPreparedPack.getStringEqualPack(workTimeStart, MesExtConstWords.WORK_TIME, packBean);

        List<MesProdDataToStatisticsShiftProd> prodDataToStatisticsShiftProdList = prodDataToStatisticsShiftProdRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(prodDataToStatisticsShiftProdList)) return null;
        List<SxShiftProdCenterRecordStatisticsModel> resultList = new ArrayList<>();
        for (MesProdDataToStatisticsShiftProd item : prodDataToStatisticsShiftProdList) {
            if (null == item || StringUtils.isEmpty(item.getProdType())) continue;
            SxShiftProdCenterRecordStatisticsModel result = new SxShiftProdCenterRecordStatisticsModel();
            BeanUtils.copyProperties(item, result);
            result.setProdName(getProdName(shiftProdMap, result.getProdType(), result.getProdCode()));
            packCenterInfo(centerMap, result);
            resultList.add(result);
        }
        return resultList;
    }

    private void packCenterInfo(Map<String, MesWorkCenterExt> centerMap, SxShiftProdCenterRecordStatisticsModel result) {
        if (!CollectionUtils.isEmpty(centerMap) && centerMap.containsKey(result.getWorkCenterCode())) {
            MesWorkCenterExt workCenterExt = centerMap.get(result.getWorkCenterCode());
            result.setWorkCenterName(workCenterExt.getWorkCenterName());
            result.setIsDont(workCenterExt.getIsDont());
        }
    }

    private List<SxShiftProdCenterRecordStatisticsModel> getMonthDataList(SxNonWorkingTimeAnalysisModel data,
                                                                          List<SxShiftProdCenterRecordStatisticsModel> yearDataList,
                                                                          Map<String, MesWorkCenterExt> centerMap, Map<String, List<MesShiftProd>> shiftProdMap) {
        List<SxShiftProdCenterRecordStatisticsModel> monthDataList;
        if (data.getWorkTime().compareTo(data.getWorkTimeStart()) < 0 || data.getWorkTime().compareTo(data.getWorkTimeEnd()) > 0) {
            if (data.getWorkTime().compareTo(data.getCurMonth()) >= 0) {
                monthDataList = getShiftProdCenterRecordList(data, data.getWorkTime() + MesExtConstWords.DATE_DD_01, null, centerMap, shiftProdMap);
            } else {
                monthDataList = getShiftProdCenterRecordStatisticsList(data, data.getWorkTime(), null, centerMap, shiftProdMap);
            }
            monthDataList = CollectionUtils.isEmpty(monthDataList) ? monthDataList :
                    monthDataList.stream().filter(o -> (null != o && centerMap.containsKey(o.getWorkCenterCode()))).collect(Collectors.toList());
        } else {
            monthDataList = CollectionUtils.isEmpty(yearDataList) ? null : yearDataList.stream().filter(o -> (null != o && o.getWorkTime().equals(data.getWorkTime()))).collect(Collectors.toList());
        }
        return monthDataList;
    }

    private void handleMonthDataList(SxNonWorkingTimeAnalysisModel data, List<SxShiftProdCenterRecordStatisticsModel> monthDataList) {
        if (CollectionUtils.isEmpty(monthDataList)) return;

        List<SxShiftProdCenterRecordStatisticsModel> stopDataList = getDataListByFlag(monthDataList, false);

        List<SxShiftProdCenterRecordStatisticsModel> itemDataList = CollectionUtils.isEmpty(stopDataList) ? null :
                stopDataList.stream().filter(o -> (null != o && MesExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_STOP_CENTER.getValue() == o.getProdType())).collect(Collectors.toList());
        Map<String, List<SxShiftProdCenterRecordStatisticsModel>> itemDataMap = CollectionUtils.isEmpty(itemDataList) ? null :
                itemDataList.stream().filter(o -> null != o).collect(Collectors.groupingBy(SxShiftProdCenterRecordStatisticsModel::getProdCode));

        List<SxShiftProdCenterRecordStatisticsModel> statisticsDataList = getDataListByFlag(monthDataList, true);

        Double noWorkingStatistics = getDataListStatistics(stopDataList);
        Double totalStatistics = getDataListStatistics(statisticsDataList);
        BigDecimal noWorkingRate = divThenMul100Format2RoundHalfUp(noWorkingStatistics, totalStatistics);

        data.addHeadData("非作业时间总计(min)", formatThousandthMark(String.valueOf(noWorkingStatistics.intValue())))
                .addHeadData("非作业时间比率", getBigDecimalPercent(noWorkingRate))
                .addHeadData("总勤务时间(min)", formatThousandthMark(String.valueOf(totalStatistics.intValue())))
                .addHeadData("BP差", getBpRatePercent(noWorkingRate, data.getPlanRate()));

        handleTableDataList(
                data, statisticsDataList, itemDataMap,
                handleCenterDataList(data, totalStatistics, stopDataList, monthDataList),
                handleItemDataList(data, totalStatistics, itemDataMap)
        );

        handlePieDataList(data, statisticsDataList, itemDataList);

        data.sortReversedMoreDataList().sortReversedTableDataList();

        restockIndex2TableDataList(data);

    }

    private static String formatThousandthMark(String value) {
        if (StringUtils.isEmpty(value)) return value;
        String[] valueArr = value.split(MesExtConstWords.DECIMAL_POINT);
        String valuePrefix = valueArr[0];
        List<String> list = new ArrayList<>();
        for (int i = valueArr[0].length(); i > 0; i -= 3) {
            if (valuePrefix.length() > 3) {
                list.add(valuePrefix.substring(valuePrefix.length() - 3));
                valuePrefix = valuePrefix.substring(0, valuePrefix.length() - 3);
            } else {
                list.add(valuePrefix);
            }
        }
        StringJoiner sj = new StringJoiner(MesExtConstWords.COMMA);
        for (int i = list.size() - 1; i >= 0; i --) {
            sj.add(list.get(i));
        }
        return valueArr.length == 2 ? new StringJoiner(MesExtConstWords.DECIMAL_POINT_STR).add(sj.toString()).add(valueArr[1]).toString() : sj.toString();
    }

    private void restockIndex2TableDataList(SxNonWorkingTimeAnalysisModel data) {
        if (CollectionUtils.isEmpty(data.getTableDataList())) return;
        Integer index = 1;
        for (Map<String, Object> tableDataMap : data.getTableDataList()) {
            if (CollectionUtils.isEmpty(tableDataMap)) continue;
            tableDataMap.put(MesExtConstWords.INDEX, index);
            index ++;
        }
    }

    private List<SxShiftProdCenterRecordStatisticsModel> getDataListByFlag(List<SxShiftProdCenterRecordStatisticsModel> dataList, Boolean flag) {
        if (CollectionUtils.isEmpty(dataList)) return null;
        if (!flag) return dataList.stream().filter(o -> (null != o && (
                MesExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_STOP_CENTER.getValue() == o.getProdType() || MesExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_STOP_CENTER.getValue() == o.getProdType()
        ))).collect(Collectors.toList());
        else return dataList.stream().filter(o -> (null != o && (
                MesExtEnumUtil.SHIFT_PROD_TYPE.NORMAL_PROD.getValue() == o.getProdType() || MesExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_PROD.getValue() == o.getProdType()
        ))).collect(Collectors.toList());
    }

    private List<String> handleCenterDataList(SxNonWorkingTimeAnalysisModel data, Double totalStatistics, List<SxShiftProdCenterRecordStatisticsModel> stopDataList, List<SxShiftProdCenterRecordStatisticsModel> monthDataList) {

        List<String> workCenterCodeList = getWorkCenterCodeList(monthDataList);

        Map<String, List<SxShiftProdCenterRecordStatisticsModel>> centerDataMap = getCenterDataMap(stopDataList);

        for (String workCenterCode : workCenterCodeList) {
            if (StringUtils.isEmpty(workCenterCode)) continue;
            data.addCenterData(workCenterCode, divThenMul100Format2RoundHalfUp(
                    getDataListStatistics(CollectionUtils.isEmpty(centerDataMap) ? null : centerDataMap.get(workCenterCode)), totalStatistics));
        }
        return workCenterCodeList;
    }

    private Map<String, List<SxShiftProdCenterRecordStatisticsModel>> getCenterDataMap(List<SxShiftProdCenterRecordStatisticsModel> dataList) {
        return CollectionUtils.isEmpty(dataList) ? null :
                dataList.stream().filter(o -> null != o).collect(Collectors.groupingBy(SxShiftProdCenterRecordStatisticsModel::getWorkCenterCode));
    }

    private List<String> handleItemDataList(SxNonWorkingTimeAnalysisModel data, Double totalStatistics, Map<String, List<SxShiftProdCenterRecordStatisticsModel>> itemDataMap) {

        if (CollectionUtils.isEmpty(itemDataMap)) return null;

        List<String> prodCodeList = new ArrayList<>(itemDataMap.keySet());
        Collections.sort(prodCodeList);

        for (String prodCode : prodCodeList) {
            if (StringUtils.isEmpty(prodCode)) continue;
            List<SxShiftProdCenterRecordStatisticsModel> itemList = itemDataMap.get(prodCode);
            data.addItemData(getProdName(itemList.get(0)), divThenMul100Format2RoundHalfUp(getDataListStatistics(itemList), totalStatistics));
        }

        return prodCodeList;
    }

    private void handlePieDataList(SxNonWorkingTimeAnalysisModel data, List<SxShiftProdCenterRecordStatisticsModel> statisticsDataList, List<SxShiftProdCenterRecordStatisticsModel> itemDataList) {
        Map<String, List<SxShiftProdCenterRecordStatisticsModel>> itemDataMap = CollectionUtils.isEmpty(itemDataList) ? null :
                itemDataList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getIsDont()))).collect(Collectors.groupingBy(SxShiftProdCenterRecordStatisticsModel::getWorkCenterCode));
        if (CollectionUtils.isEmpty(itemDataMap)) return;

        Map<String, List<SxShiftProdCenterRecordStatisticsModel>> statisticsDataMap = statisticsDataList.stream().filter(o ->
                (null != o && !StringUtils.isEmpty(o.getIsDont()))).collect(Collectors.groupingBy(SxShiftProdCenterRecordStatisticsModel::getWorkCenterCode));

        Double itemStatistics = getDataListStatistics(itemDataList);
        for (Map.Entry<String, List<SxShiftProdCenterRecordStatisticsModel>> entry : itemDataMap.entrySet()) {
            if (null == entry) continue;
            Double statistics = getDataListStatistics(entry.getValue());
            Double monthStatistics = getDataListStatistics(statisticsDataMap.get(entry.getKey()));
            BigDecimal rate = divThenMul100Format2RoundHalfUp(statistics, itemStatistics);
            data.addPieData(entry.getKey(), rate, getPieShowData(entry.getKey(), statistics, monthStatistics, rate));
        }
    }

    private void handleTableDataList(SxNonWorkingTimeAnalysisModel data, List<SxShiftProdCenterRecordStatisticsModel> statisticsDataList,
                                     Map<String, List<SxShiftProdCenterRecordStatisticsModel>> itemDataMap, List<String> workCenterCodeList, List<String> prodCodeList) {
        handleTableNameList(data, workCenterCodeList);

        if (CollectionUtils.isEmpty(prodCodeList)) return;

        Map<String, Double> centerStatisticsMap = getCenterStatisticsMap(statisticsDataList);

        for (String prodCode : prodCodeList) {
            if (StringUtils.isEmpty(prodCode)) continue;
            List<SxShiftProdCenterRecordStatisticsModel> itemList = itemDataMap.get(prodCode);
            Map<String, List<SxShiftProdCenterRecordStatisticsModel>> centerItemMap = getCenterDataMap(itemList);

            Map<String, Object> tableDataMap = new HashMap<>();
            tableDataMap.put(MesExtConstWords.PROD_NAME, itemList.get(0).getProdName());
            tableDataMap.put(MesExtConstWords.PROD_TYPE_NAME, MesExtEnumUtil.SHIFT_PROD_TYPE.UNNORMAL_STOP_CENTER.getDescription());
            for (String workCenterCode : workCenterCodeList) {
                if (StringUtils.isEmpty(workCenterCode)) continue;
                tableDataMap.put(workCenterCode, getTableCenterData(workCenterCode, centerItemMap, centerStatisticsMap));
            }
            tableDataMap.put(MesExtConstWords.TOTAL, getDataListStatistics(itemList));
            data.addTableData(tableDataMap);
        }

    }

    private void handleYearDataList(SxNonWorkingTimeAnalysisModel data, List<SxShiftProdCenterRecordStatisticsModel> yearDataList) {

        if (CollectionUtils.isEmpty(yearDataList)) return;

        Map<String, List<SxShiftProdCenterRecordStatisticsModel>> monthDataMap = CollectionUtils.isEmpty(yearDataList) ? null :
                yearDataList.stream().filter(o -> null != o).collect(Collectors.groupingBy(SxShiftProdCenterRecordStatisticsModel::getWorkTime));

        String month = data.getWorkTimeStart();
        for (int i = 1; i < 13; i ++) {
            List<SxShiftProdCenterRecordStatisticsModel> monthDataList = monthDataMap.get(month);
            BigDecimal serviceTime = calcYearDataStatistics(monthDataList, true);
            BigDecimal nonWorkingTime = calcYearDataStatistics(monthDataList, false);
            BigDecimal workingTime = format2RoundHalfUp(MathOperation.sub(serviceTime.doubleValue(), nonWorkingTime.doubleValue()));
            data.addBarData(Integer.valueOf(month.substring(5)).toString(), nonWorkingTime, workingTime, divThenMul100Format2RoundHalfUp(nonWorkingTime.doubleValue(), serviceTime.doubleValue()));
            month = TimeTool.timeCalc(TimeTool.stringParseToDate(month, MesExtConstWords.DATE_FORMAT_YM), Calendar.MONTH, 1, MesExtConstWords.DATE_FORMAT_YM);
        }
    }

    private BigDecimal calcYearDataStatistics(List<SxShiftProdCenterRecordStatisticsModel> monthDataList, Boolean flag) {
        List<SxShiftProdCenterRecordStatisticsModel> dataList = getDataListByFlag(monthDataList, flag);
        return format2RoundHalfUp(MathOperation.div(getDataListStatistics(dataList), new Double(1000)));
    }

    private String getTableCenterData(String workCenterCode, Map<String, List<SxShiftProdCenterRecordStatisticsModel>> centerItemMap, Map<String, Double> centerStatisticsMap) {
        List<SxShiftProdCenterRecordStatisticsModel> centerItemList = CollectionUtils.isEmpty(centerItemMap) ? null : centerItemMap.get(workCenterCode);
        Double statistics = (CollectionUtils.isEmpty(centerStatisticsMap) || !centerStatisticsMap.containsKey(workCenterCode)) ? new Double(0) : centerStatisticsMap.get(workCenterCode);
        return getBigDecimalPercent(divThenMul100Format2RoundHalfUp(getDataListStatistics(centerItemList), statistics));
    }

    private Map<String, Double> getCenterStatisticsMap(List<SxShiftProdCenterRecordStatisticsModel> statisticsDataList) {
        Map<String, List<SxShiftProdCenterRecordStatisticsModel>> statisticsDataMap = getCenterDataMap(statisticsDataList);
        if (CollectionUtils.isEmpty(statisticsDataMap)) return null;
        Map<String, Double> centerStatisticsMap = new HashMap<>();
        for (Map.Entry<String, List<SxShiftProdCenterRecordStatisticsModel>> entry : statisticsDataMap.entrySet()) {
            centerStatisticsMap.put(entry.getKey(), getDataListStatistics(entry.getValue()));
        }
        return centerStatisticsMap;
    }

    private void handleTableNameList(SxNonWorkingTimeAnalysisModel data, List<String> workCenterCodeList) {
        data.addTableName(MesExtConstWords.INDEX, "序号").addTableName(MesExtConstWords.PROD_NAME, "停机项目").addTableName(MesExtConstWords.PROD_TYPE_NAME, "停机类型");
        for (String workCenterCode : workCenterCodeList) {
            data.addTableName(workCenterCode, workCenterCode);
        }
    }

    private String getPieShowData(String isDont, Double statistics, Double monthStatistics, BigDecimal rate) {
        return isDont + MesExtConstWords.COLON + getBigDecimalPercent(divThenMul100Format2RoundHalfUp(statistics, monthStatistics)) + MesExtConstWords.COMMA + "占:" + getBigDecimalPercent(rate);
    }

    private List<String> getWorkCenterCodeList(List<SxShiftProdCenterRecordStatisticsModel> monthDataList) {
        List<String> workCenterCodeList = monthDataList.stream().filter(o -> null != o).map(SxShiftProdCenterRecordStatisticsModel::getWorkCenterCode).collect(Collectors.toList());
        workCenterCodeList = workCenterCodeList.stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
        Collections.sort(workCenterCodeList);
        return workCenterCodeList;
    }

    private String getProdName(SxShiftProdCenterRecordStatisticsModel item) {
        return !StringUtils.isEmpty(item.getProdName()) ? item.getProdName() : item.getProdCode();
    }

    private String getBpRatePercent(BigDecimal noWorkingRate, String planRate) {
        Double bpRate = MathOperation.sub(noWorkingRate.doubleValue(), divThenMul100Format2RoundHalfUp(new Double(planRate), new Double(1)).doubleValue());
        return format2(bpRate) + MesExtConstWords.PERCENT;
    }

    private Double getDataListStatistics(List<SxShiftProdCenterRecordStatisticsModel> dataList) {
        return CollectionUtils.isEmpty(dataList) ? new Double(0) :
                dataList.stream().filter(o -> null != o).mapToDouble(SxShiftProdCenterRecordStatisticsModel::getStatistics).sum();
    }

    private String getBigDecimalPercent(BigDecimal b) {
        return b + MesExtConstWords.PERCENT;
    }

    private BigDecimal divThenMul100Format2RoundHalfUp(Double d1, Double d2) {
        Double d = (MathOperation.compareTo(d1, new Double(0)) == 0 || MathOperation.compareTo(d2, new Double(0)) == 0)
                ? null : MathOperation.mul(MathOperation.div(d1, d2), new Double(100));
        return format2RoundHalfUp(d);
    }

    private BigDecimal format2RoundHalfUp(Double d) {
        if (StringUtils.isEmpty(d)) d = new Double(0);
        BigDecimal bd = new BigDecimal(d);
        bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
        return bd;
    }

    private String format2(Double d) {
        return String.format("%.2f", d);
    }

}
