package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.job;

import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderOfflineRestoreDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderOfflineRestoreService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
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.offline.MesWorkOrderAssemblyOffline;
import cn.estsh.i3plus.pojo.mes.bean.offline.MesWorkOrderOffline;
import cn.estsh.i3plus.pojo.mes.repository.offline.MesWorkOrderAssemblyOfflineRepository;
import cn.estsh.i3plus.pojo.mes.repository.offline.MesWorkOrderOfflineRepository;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MesWorkOrderOfflineRestoreService implements IMesWorkOrderOfflineRestoreService {

    @Autowired
    private MesWorkOrderAssemblyOfflineRepository workOrderAssemblyOfflineRepository;

    @Autowired
    private MesWorkOrderOfflineRepository workOrderOfflineRepository;

    @Autowired
    private IMesWorkOrderOfflineRestoreDispatchService workOrderOfflineRestoreDispatchService;

    @Override
    public void doRestoreWorkOrderOfflineData(Map<String, String> paramMap) {

        //参数 工厂
        String organizeCode = paramMap.get(MesPcnExtConstWords.ORGANIZE_CODE);

        //参数 处理数据量
        Integer qty = paramMap.containsKey(MesPcnExtConstWords.QTY) ? Integer.valueOf(paramMap.get(MesPcnExtConstWords.QTY)) : MesPcnExtConstWords.ONE_HUNDRED;

        //查询工单离线数据 [未处理]
        List<MesWorkOrderOffline> workOrderOfflineList = getWorkOrderOfflineList(organizeCode, qty);

        //搜集工单号 [未处理]
        List<String> workOrderNoList = CollectionUtils.isEmpty(workOrderOfflineList) ? null :
                workOrderOfflineList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkOrderNo()))).map(MesWorkOrderOffline::getWorkOrderNo).collect(Collectors.toList());

        log.info("补录离线生产工单数据JOB --- 查询到未补录完成的生产工单包含: {} ---", CollectionUtils.isEmpty(workOrderNoList) ? "[]" : workOrderNoList.toString());

        //查询工单装配件离线数据 [未处理]
        List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList = getWorkOrderAssemblyOfflineList(organizeCode, qty);

        if (CollectionUtils.isEmpty(workOrderNoList) && CollectionUtils.isEmpty(workOrderAssemblyOfflineList)) return;

        String now = TimeTool.getNowTime(true);

        //[未处理]
        if (!CollectionUtils.isEmpty(workOrderNoList)) {
            //查询排序工单装配件离线数据[未同步的数据] 根据工单号分组
            Map<String, List<MesWorkOrderAssemblyOffline>> workOrderAssemblyOfflineMap = getWorkOrderAssemblyOfflineMap(organizeCode, workOrderNoList);

            //补录生产数据 [未处理]
            workOrderOfflineList.forEach(o -> doRestoreWorkOrderOfflineData(organizeCode, o, getWorkOrderAssemblyOfflineList(workOrderAssemblyOfflineMap, o.getWorkOrderNo()), now, false));
        }

        //剔除上面已经处理过的工单的 装配件数据 [补偿处理]
        workOrderAssemblyOfflineList = CollectionUtils.isEmpty(workOrderAssemblyOfflineList) ? null :
                workOrderAssemblyOfflineList.stream().filter(o -> (null != o && !workOrderNoList.contains(o.getWorkOrderNo()))).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(workOrderAssemblyOfflineList)) return;

        //根据工单号分组 [补偿处理]
        Map<String, List<MesWorkOrderAssemblyOffline>> workOrderAssemblyOfflineMap = backWorkOrderAssemblyMap(workOrderAssemblyOfflineList);

        //查询工单离线数据  [已处理]
        workOrderOfflineList = getWorkOrderOfflineMap(organizeCode, new ArrayList<>(workOrderAssemblyOfflineMap.keySet()));

        if (CollectionUtils.isEmpty(workOrderOfflineList)) return;

        //补录生产数据 [补偿处理]
        workOrderOfflineList.forEach(o -> doRestoreWorkOrderOfflineData(organizeCode, o, getWorkOrderAssemblyOfflineList(workOrderAssemblyOfflineMap, o.getWorkOrderNo()), now, true));

    }

    //查询工单离线数据 [未处理]
    private List<MesWorkOrderOffline> getWorkOrderOfflineList(String organizeCode, Integer qty) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.SYSTEM_SYNC_STATUS, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.MODIFY_DATE_TIME}, packBean);
        List<MesWorkOrderOffline> workOrderOfflineList = workOrderOfflineRepository.findByHqlTopWhere(packBean, qty);
        return workOrderOfflineList;
    }

    //查询工单离线数据 [已处理]
    private List<MesWorkOrderOffline> getWorkOrderOfflineMap(String organizeCode, List<String> workOrderNoList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), MesPcnExtConstWords.SYSTEM_SYNC_STATUS, packBean);
        DdlPreparedPack.getInPackList(workOrderNoList, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        List<MesWorkOrderOffline> workOrderOfflineList = workOrderOfflineRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(workOrderOfflineList)) return null;
        workOrderOfflineList = workOrderOfflineList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesWorkOrderOffline::getModifyDatetime).reversed()).collect(Collectors.toList());
        return workOrderOfflineList.stream().filter(o -> null != o).distinct().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MesWorkOrderOffline::getWorkOrderNo))), ArrayList::new));
    }

    //查询工单装配件离线数据 [未处理]
    private List<MesWorkOrderAssemblyOffline> getWorkOrderAssemblyOfflineList(String organizeCode, Integer qty) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.SYSTEM_SYNC_STATUS, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.MODIFY_DATE_TIME}, packBean);
        List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList = workOrderAssemblyOfflineRepository.findByHqlTopWhere(packBean, qty);
        return workOrderAssemblyOfflineList;
    }

    //查询排序工单装配件离线数据[未同步的数据]
    private Map<String, List<MesWorkOrderAssemblyOffline>> getWorkOrderAssemblyOfflineMap(String organizeCode, List<String> workOrderNoList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtConstWords.SYSTEM_SYNC_STATUS, packBean);
        DdlPreparedPack.getInPackList(workOrderNoList, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList = workOrderAssemblyOfflineRepository.findByHqlWhere(packBean);
        if (CollectionUtils.isEmpty(workOrderAssemblyOfflineList)) log.info("--- 异常 --- 补录离线生产工单数据JOB --- 当前没有需要补录的工单装配件离线数据 ---");
        return backWorkOrderAssemblyMap(workOrderAssemblyOfflineList);
    }

    //搜集数据
    private List<MesWorkOrderAssemblyOffline> getWorkOrderAssemblyOfflineList(Map<String, List<MesWorkOrderAssemblyOffline>> workOrderAssemblyOfflineMap, String workOrderNo) {
        return CollectionUtils.isEmpty(workOrderAssemblyOfflineMap) ? null : workOrderAssemblyOfflineMap.get(workOrderNo);
    }

    //根据工单号分组
    private Map<String, List<MesWorkOrderAssemblyOffline>> backWorkOrderAssemblyMap(List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList) {
        return workOrderAssemblyOfflineList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesWorkOrderAssemblyOffline::getWorkOrderNo));
    }

    //补录生产数据
    private void doRestoreWorkOrderOfflineData(String organizeCode, MesWorkOrderOffline workOrderOffline, List<MesWorkOrderAssemblyOffline> workOrderAssemblyOfflineList, String now, Boolean flag) {
        log.info("补录离线生产工单数据JOB --- 工单:{} --- START ---", workOrderOffline.getWorkOrderNo());
        Boolean result = false;
        try {
            result = workOrderOfflineRestoreDispatchService.doRestoreWorkOrderOfflineData(organizeCode, workOrderOffline, workOrderAssemblyOfflineList, now, flag);
        } catch (Exception e) {
            if (flag) result = true;
            log.info("--- 异常 --- 补录离线生产工单数据JOB --- 工单:{} --- ERROR --- {}", workOrderOffline.getWorkOrderNo(), e.toString());
        } finally {
            workOrderOfflineRestoreDispatchService.saveWorkOrderOffline(workOrderOffline, result);
            log.info("补录离线生产工单数据JOB --- 工单:{} --- END --- result={} --- MesWorkOrderOffline={}", workOrderOffline.getWorkOrderNo(), result, JSONObject.toJSONString(workOrderOffline));
        }
    }

}
