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

import cn.estsh.i3plus.ext.mes.api.base.IMesAccidentDateService;
import cn.estsh.i3plus.ext.mes.api.base.IMesNumberOfSafeOperationDaysService;
import cn.estsh.i3plus.ext.mes.api.base.bu.IBusiConfigService;
import cn.estsh.i3plus.ext.mes.api.busi.jx.IJxCenterWorkingBoardService;
import cn.estsh.i3plus.ext.mes.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pojo.model.MesAccidentDateModel;
import cn.estsh.i3plus.ext.mes.pojo.model.bu.MesNumberOfSafeOperationDaysModel;
import cn.estsh.i3plus.ext.mes.pojo.model.jx.JxCenterWorkingBoardBusiModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesOutPutStatisticsRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesPlantInfoRepository;
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 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.util.*;
import java.util.stream.Collectors;

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

    private IJxCenterWorkingBoardService proxyService0;

    private IJxCenterWorkingBoardService proxyService1;

    private IJxCenterWorkingBoardService proxyService2;

    private IJxCenterWorkingBoardService proxyService3;

    private IJxCenterWorkingBoardService proxyService;

    private MesPlantInfoRepository plantInfoRepository;

    private IMesNumberOfSafeOperationDaysService numberOfSafeOperationDaysService;

    private IMesAccidentDateService accidentDateService;

    private IBusiConfigService busiConfigService;

    private MesOutPutStatisticsRepository outPutStatisticsRepository;

    public JxCenterWorkingBoardMonitorOneService(IJxCenterWorkingBoardService proxyService0, IJxCenterWorkingBoardService proxyService1, IJxCenterWorkingBoardService proxyService2, IJxCenterWorkingBoardService proxyService3, IJxCenterWorkingBoardService proxyService) {
        this.proxyService0 = proxyService0;
        this.proxyService1 = proxyService1;
        this.proxyService2 = proxyService2;
        this.proxyService3 = proxyService3;
        this.proxyService = proxyService;
        this.plantInfoRepository = (MesPlantInfoRepository) SpringContextsUtil.getBean("mesPlantInfoRepository");
        this.numberOfSafeOperationDaysService = (IMesNumberOfSafeOperationDaysService) SpringContextsUtil.getBean("mesNumberOfSafeOperationDaysService");
        this.accidentDateService = (IMesAccidentDateService) SpringContextsUtil.getBean("mesAccidentDateService");
        this.busiConfigService = (IBusiConfigService) SpringContextsUtil.getBean("busiConfigService");
        this.outPutStatisticsRepository = (MesOutPutStatisticsRepository) SpringContextsUtil.getBean("mesOutPutStatisticsRepository");
    }

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

        dataMap = proxyService0.queryCenterWorkingBoardData(dataMap);

        dataMap = proxyService1.queryCenterWorkingBoardData(dataMap);

        List<MesWorkCenterExt> workCenterExtDbList = (List<MesWorkCenterExt>) dataMap.get(MesWorkCenterExt.class.getSimpleName());

        packProxyCondition(dataMap, workCenterExtDbList);

        dataMap = proxyService.queryCenterWorkingBoardData(dataMap);

        String organizeCode = (String) dataMap.get(MesExtConstWords.ORGANIZE_CODE);

        dataMap.put("BOARD_TITLE", "PKATJX智能工场监控中心");

        dataMap.put("BOARD_BOTTOM", "PKATJX·松下厨电科技（嘉兴）有限公司");

        dataMap.put("工厂信息总览", getOrganizeInfo(organizeCode));

        dataMap.put("累计安全运行天数", getAmountSafeRunningDays(organizeCode));

        dataMap.put("当年累计总事故数", getCurYearAmountAccident(organizeCode));

        dataMap.put("生产进度", getProductionSchedule(organizeCode, workCenterExtDbList, dataMap));

        calcOntologyLineData(organizeCode, workCenterExtDbList, dataMap);

        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.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);
        dataMap.remove(MesExtConstWords.STATUS);
        dataMap.remove("serviceTime");
        dataMap.remove("nonWorkingTime");
        dataMap.remove("standardTime");
        dataMap.remove("workingTime");
        dataMap.remove("curTime");
        return dataMap;
    }

    private void packProxyCondition(Map<String, Object> dataMap, List<MesWorkCenterExt> workCenterExtDbList) {
        List<String> workTimeList = workCenterExtDbList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkTime()) && !StringUtils.isEmpty(o.getShiftCode()))).map(MesWorkCenterExt::getWorkTime).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(workTimeList)) return;
        Collections.sort(workTimeList);
        dataMap.put(MesExtConstWords.START_TIME, workTimeList.get(0));
        dataMap.put(MesExtConstWords.END_TIME, workTimeList.get(workTimeList.size() - 1));
        dataMap.put("curTime", TimeTool.getNowTime(true));
    }

    private MesPlantInfo getOrganizeInfo(String organizeCode) {
        return plantInfoRepository.getByProperty(
                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()});
    }

    private MesNumberOfSafeOperationDaysModel getAmountSafeRunningDays(String organizeCode) {
        return numberOfSafeOperationDaysService.queryBuNumberOfSafeOperationDaysBoard(organizeCode);
    }

    private MesAccidentDateModel getCurYearAmountAccident(String organizeCode) {
        return accidentDateService.queryBuAccidentDaysBoard(organizeCode);
    }

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

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

    private JxCenterWorkingBoardBusiModel getProductionSchedule(String organizeCode, List<MesWorkCenterExt> workCenterExtDbList, Map<String, Object> dataMap) {

        JxCenterWorkingBoardBusiModel psData = new JxCenterWorkingBoardBusiModel().title("生产进度");

        List<MesWorkOrder> workOrderList = (List<MesWorkOrder>) dataMap.get(MesWorkOrder.class.getSimpleName());
        List<MesOutPutStatistics> outPutStatisticsList = (List<MesOutPutStatistics>) dataMap.get(MesOutPutStatistics.class.getSimpleName());
        if (CollectionUtils.isEmpty(workOrderList) && CollectionUtils.isEmpty(outPutStatisticsList)) return psData;

        String categoryCodeCfg4Cached = (String) execCachedCenterWorkingBoardData(organizeCode, MesExtConstWords.ZERO_STR, MesExtConstWords.SX_CATEGORY_CFG, null);
        MesBusiConfig categoryCodeCfg = !StringUtils.isEmpty(categoryCodeCfg4Cached) ? JSONObject.parseObject(categoryCodeCfg4Cached, MesBusiConfig.class) : execCatagoryCodeCfg(organizeCode);
        if (null == categoryCodeCfg || StringUtils.isEmpty(categoryCodeCfg.getCfgValue()) || StringUtils.isEmpty(categoryCodeCfg.getCfgValueSeq())) return psData;

        String[] categoryCodeArr = categoryCodeCfg.getCfgValueSeq().split(MesExtConstWords.COMMA);
        String[] categoryNameArr = categoryCodeCfg.getCfgValue().split(MesExtConstWords.COMMA);
        if (categoryCodeArr.length != categoryNameArr.length) return psData;

        Map<String, List<MesOutPutStatistics>> centerMap4OutPutFilter = new HashMap<>();

        Map<String, List<MesWorkOrder>> centerMap4Order = getCenterMap4Order(workOrderList);
        Map<String, List<MesOutPutStatistics>> centerMap4OutPut = getCenterMap4OutPut(outPutStatisticsList);

        Map<String, List<MesWorkOrder>> categoryCodeMap4Order = new HashMap<>();
        Map<String, List<MesOutPutStatistics>> categoryCodeMap4OutPut = new HashMap<>();

        for (MesWorkCenterExt workCenterExtDb : workCenterExtDbList) {
            if (null == workCenterExtDb) continue;
            if (StringUtils.isEmpty(workCenterExtDb.getCategoryCode()) || StringUtils.isEmpty(workCenterExtDb.getWorkTime()) || StringUtils.isEmpty(workCenterExtDb.getShiftCode())) continue;

            List<MesWorkOrder> workOrderList4Center = CollectionUtils.isEmpty(centerMap4Order) ? null : getWorkOrderListByWorkTime(centerMap4Order.get(workCenterExtDb.getWorkCenterCode()), workCenterExtDb.getWorkTime());
            List<MesOutPutStatistics> outPutStatisticsList4Center = CollectionUtils.isEmpty(centerMap4OutPut) ? null : getOutPutStatisticsListByWorkTime(centerMap4OutPut.get(workCenterExtDb.getWorkCenterCode()), workCenterExtDb.getWorkTime());

            List<MesWorkOrder> categoryCodeList4Order = (!CollectionUtils.isEmpty(categoryCodeMap4Order) && categoryCodeMap4Order.containsKey(workCenterExtDb.getCategoryCode())) ? categoryCodeMap4Order.get(workCenterExtDb.getCategoryCode()) : new ArrayList<>();
            List<MesOutPutStatistics> categoryCodeList4OutPut = (!CollectionUtils.isEmpty(categoryCodeMap4OutPut) && categoryCodeMap4OutPut.containsKey(workCenterExtDb.getCategoryCode())) ? categoryCodeMap4OutPut.get(workCenterExtDb.getCategoryCode()) : new ArrayList<>();
            if (!CollectionUtils.isEmpty(workOrderList4Center)) categoryCodeList4Order.addAll(workOrderList4Center);
            if (!CollectionUtils.isEmpty(outPutStatisticsList4Center)) categoryCodeList4OutPut.addAll(outPutStatisticsList4Center);

            categoryCodeMap4Order.put(workCenterExtDb.getCategoryCode(), categoryCodeList4Order);
            categoryCodeMap4OutPut.put(workCenterExtDb.getCategoryCode(), categoryCodeList4OutPut);

            if (!CollectionUtils.isEmpty(outPutStatisticsList4Center)) centerMap4OutPutFilter.put(workCenterExtDb.getWorkCenterCode(), sortOutPutStatisticsList(outPutStatisticsList4Center));
        }

        for (int i = 0; i < categoryCodeArr.length; i ++) {
            List<MesWorkOrder> workOrderList4Category = CollectionUtils.isEmpty(categoryCodeMap4Order) ? null : categoryCodeMap4Order.get(categoryCodeArr[i]);
            List<MesOutPutStatistics> outPutStatisticsList4Category = CollectionUtils.isEmpty(categoryCodeMap4OutPut) ? null : categoryCodeMap4OutPut.get(categoryCodeArr[i]);

            Double planQtyAmount = getWorkOrderList2AmountQty(workOrderList4Category);
            Double completeQtyAmount = getOutPutStatisticsList2AmountQty(outPutStatisticsList4Category);

            psData.addChartData(categoryNameArr[i], completeQtyAmount, planQtyAmount, getBigDecimalPercent(divThenMul100Format1RoundHalfUp(completeQtyAmount, planQtyAmount)));
        }

        dataMap.put(MesOutPutStatistics.class.getSimpleName(), centerMap4OutPutFilter);

        return psData;
    }

    private Map<String, Object> calcOntologyLineData(String organizeCode, List<MesWorkCenterExt> workCenterExtDbList, Map<String, Object> dataMap) {

        JxCenterWorkingBoardBusiModel psData1 = new JxCenterWorkingBoardBusiModel().title("本体产线状态");
        JxCenterWorkingBoardBusiModel psData2 = new JxCenterWorkingBoardBusiModel().title("本体能率");

        String busiConfigList4Cached = (String) execCachedCenterWorkingBoardData(organizeCode, MesExtConstWords.ZERO_STR, MesExtConstWords.BOARD_WORK_SHOW_FLAG, null);
        List<MesBusiConfig> busiConfigList = !StringUtils.isEmpty(busiConfigList4Cached) ? JSONObject.parseArray(busiConfigList4Cached, MesBusiConfig.class) : execConfigListSortSeq(organizeCode);
        if (CollectionUtils.isEmpty(busiConfigList)) return packOntologyLineWorkingStatusAndEnergyRate(dataMap, psData1, psData2);

        Map<String, MesWorkCenterExt> workCenterExtDbMap = workCenterExtDbList.stream().filter(o -> null != o).collect(Collectors.toMap(MesWorkCenterExt::getWorkCenterCode, o -> o));

        Map<String, List<MesOutPutStatistics>> centerMap4OutPutFilter = (Map<String, List<MesOutPutStatistics>>) dataMap.get(MesOutPutStatistics.class.getSimpleName());
        List<MesRepairTask> repairTaskList = (List<MesRepairTask>) dataMap.get(MesRepairTask.class.getSimpleName());

        for (MesBusiConfig busiConfig : busiConfigList) {
            if (null == busiConfig || !workCenterExtDbMap.containsKey(busiConfig.getCfgValue())) continue;
            MesWorkCenterExt workCenterExtDb = workCenterExtDbMap.get(busiConfig.getCfgValue());
            if (StringUtils.isEmpty(workCenterExtDb.getLineType()) || !workCenterExtDb.getLineType().equals(MesExtEnumUtil.LINE_TYPE.ONTOLOGY_LINE.getValueStr())) continue;
            dataMap.put(MesExtConstWords.WORK_TIME, workCenterExtDb.getWorkTime());
            dataMap.put(MesExtConstWords.SHIFT_CODE, workCenterExtDb.getShiftCode());
            dataMap.put(MesExtConstWords.WORK_CENTER_CODE, workCenterExtDb.getWorkCenterCode());

            List<MesOutPutStatistics> outPutStatisticsListFilter = CollectionUtils.isEmpty(centerMap4OutPutFilter) ? null : centerMap4OutPutFilter.get(workCenterExtDb.getWorkCenterCode());
            dataMap.put(MesOutPutStatistics.class.getSimpleName(), outPutStatisticsListFilter);

            MesOutPutStatistics outPutStatistics = !CollectionUtils.isEmpty(outPutStatisticsListFilter) ? outPutStatisticsListFilter.get(0) : getOutPutStatisticsByCenter(organizeCode, workCenterExtDb.getWorkCenterCode());
            List<MesOutPutStatistics> outPutStatisticsList2Order = (null == outPutStatistics || CollectionUtils.isEmpty(outPutStatisticsListFilter)) ? null : outPutStatisticsListFilter.stream().filter(o -> (null != o && o.getWorkOrderNo().equals(outPutStatistics.getWorkOrderNo()))).collect(Collectors.toList());

            psData1.addChartData(workCenterExtDb.getWorkCenterCode(), null == outPutStatistics ? null : outPutStatistics.getPartNo(), getRepairRate(outPutStatisticsList2Order, repairTaskList, workCenterExtDb), proxyService2.queryCenterWorkingBoardData(dataMap).get(MesExtConstWords.STATUS));

            proxyService3.queryCenterWorkingBoardData(dataMap);

            psData2.addChartData(workCenterExtDb.getWorkCenterCode(),
                    getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get("standardTime"), (Double) dataMap.get("workingTime"))),
                    getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get("workingTime"), (Double) dataMap.get("serviceTime"))),
                    getBigDecimalPercent(divThenMul100Format1RoundHalfUp((Double) dataMap.get("standardTime"), (Double) dataMap.get("serviceTime"))));

        }

        return packOntologyLineWorkingStatusAndEnergyRate(dataMap, psData1, psData2);
    }

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

    private List<MesBusiConfig> execConfigListSortSeq(String organizeCode) {
        List<MesBusiConfig> busiConfigList = busiConfigService.getConfigListSortSeq(organizeCode, MesExtConstWords.BOARD_WORK_SHOW_FLAG);
        if (!CollectionUtils.isEmpty(busiConfigList)) execCachedCenterWorkingBoardData(organizeCode, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr(), MesExtConstWords.BOARD_WORK_SHOW_FLAG, JSONObject.toJSONString(busiConfigList));
        return busiConfigList;
    }

    private Map<String, Object> packOntologyLineWorkingStatusAndEnergyRate(Map<String, Object> dataMap, JxCenterWorkingBoardBusiModel psData1, JxCenterWorkingBoardBusiModel psData2) {
        dataMap.put("本体产线状态", psData1);
        dataMap.put("本体能率", psData2);
        return dataMap;
    }

    private String getRepairRate(List<MesOutPutStatistics> outPutStatisticsList, List<MesRepairTask> repairTaskList, MesWorkCenterExt workCenterExtDb) {
        return (CollectionUtils.isEmpty(outPutStatisticsList) || StringUtils.isEmpty(workCenterExtDb.getWorkTime())) ? getBigDecimalPercent(format1RounHalfUp(new Double(0))) : calcRepairRate(outPutStatisticsList, repairTaskList, workCenterExtDb);
    }

    private String calcRepairRate(List<MesOutPutStatistics> outPutStatisticsList, List<MesRepairTask> repairTaskList, MesWorkCenterExt workCenterExtDb) {
        Double repairQty = CollectionUtils.isEmpty(repairTaskList) ? new Double(0) : getListSizeD(repairTaskList.stream().filter(o -> (null != o && o.getWorkOrderNo().equals(outPutStatisticsList.get(0).getWorkOrderNo()) && o.getWorkTime().equals(workCenterExtDb.getWorkTime()))).collect(Collectors.toList()));
        Double qty = getOutPutStatisticsList2AmountQty(outPutStatisticsList);
        return getBigDecimalPercent(format1RounHalfUp(MathOperation.sub(new Double(100), MathOperation.div(qty, MathOperation.add(qty, repairQty)))));
    }

    private MesOutPutStatistics getOutPutStatisticsByCenter(String organizeCode, String workCenterCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.WORK_ORDER_TYPE.STANDARD_ORDER.getValue(), MesExtConstWords.WORK_ORDER_TYPE, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesExtConstWords.MODIFY_DATE_TIME}, packBean);
        return outPutStatisticsRepository.getByProperty(packBean);
    }

}
