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

import cn.estsh.i3plus.ext.mes.pcn.api.job.ep.IEpProductDataRfidMatchService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.step.ep.EpCollectDbProductDataStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProductDataRfidRecord;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesProductDataRfidRecordRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IConfigService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
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.MesConfig;
import cn.estsh.i3plus.pojo.mes.bean.MesProductData;
import cn.estsh.i3plus.pojo.mes.repository.MesConfigRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesProductDataRepository;
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.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: wangjie
 * @CreateDate: 2019/8/23 1:16 PM
 * @Description: Pcn生产数据RFID匹配定时任务
 **/
@Slf4j
@Service
public class EpProductDataRfidMatchService implements IEpProductDataRfidMatchService {

    @Autowired
    private MesProductDataRfidRecordRepository productDataRfidRecordRepository;

    @Autowired
    private MesProductDataRepository productDataRepository;

    @Autowired
    private IConfigService configService;

    @Autowired
    private MesConfigRepository configRepository;

    @Autowired
    private EpCollectDbProductDataStepService collectDbProductDataStepService;

    private static final String INITIAL_TIME = "1970-01-01 00:00:00";

    @Override
    public void doProductDataRfidMatch(String organizeCode) {
        MesConfig config = getPdRfidMatchCfg(organizeCode);
        if (null == config) {
            log.info("Pcn生产数据RFID匹配JOB,未获取生产数据采集RFID数据处理时间配置");
            config = new MesConfig();
            packNewConfig(config, organizeCode);
        }

        String startDateTime;
        try {
            startDateTime = doCalcStartDate(config.getCfgValue());
        } catch (Exception e) {
            log.info("Pcn生产数据RFID匹配JOB,未获取的起始时间");
            return;
        }
        log.info("Pcn生产数据RFID匹配JOB,获取的起始时间[{}]", startDateTime);

        List<MesProductData> productDataList = getProductDataList(organizeCode, startDateTime);
        if (CollectionUtils.isEmpty(productDataList)) {
            log.info("Pcn生产数据RFID匹配JOB,未获取到生产数据");
            return;
        }
        log.info("Pcn生产数据RFID匹配JOB,获取的生产数据集合数据量[{}]", productDataList.size());

        List<String> groupNoList = getGroupNoList(productDataList);
        if (CollectionUtils.isEmpty(groupNoList)) {
            log.info("Pcn生产数据RFID匹配JOB,获取的生产数据集合未能筛选出的RFID匹配值数据");
            return;
        }
        log.info("Pcn生产数据RFID匹配JOB,获取的生产数据集合筛选出的RFID匹配值数据量[{}]:{}", groupNoList.size(), groupNoList.toString());

        Map<String, MesProductDataRfidRecord> rfidRecordMap = getRfidRecordMap(organizeCode, groupNoList);
        if (CollectionUtils.isEmpty(rfidRecordMap)) {
            log.info("Pcn生产数据RFID匹配JOB,根据获取的所有RFID匹配值数据均未查询到采集数据RFID记录信息");
            return;
        }

        log.info("Pcn生产数据RFID匹配JOB,开始执行生产数据RFID匹配");
        List<String> savedDataList = saveProductData(productDataList, rfidRecordMap);
        log.info("Pcn生产数据RFID匹配JOB,生产数据RFID匹配成功的数据量[{}],ID&RFID:{}", savedDataList.size(), savedDataList.toString());

        productDataList = productDataList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesProductData::getCreateDatetime)).collect(Collectors.toList());
        log.info("Pcn生产数据RFID匹配JOB,获取到的生产数据根据创建时间已重新排序");

        savePdRfidMatchCfg(config, reGetStartDateTime(productDataList));

        log.info("Pcn生产数据RFID匹配JOB执行成功,起始时间变更为[{}]", config.getCfgValue());
    }

    private void savePdRfidMatchCfg(MesConfig config, String startDateTime) {
        config.setCfgValue(startDateTime);
        if (StringUtils.isEmpty(config.getId())) {
            ConvertBean.serviceModelInitialize(config, MesPcnExtConstWords.JOB);
            configRepository.insert(config);
        } else {
            ConvertBean.serviceModelUpdate(config, MesPcnExtConstWords.JOB);
            configRepository.save(config);
        }
    }

    private String reGetStartDateTime(List<MesProductData> productDataList) {
        String startDateTime;
        Optional<MesProductData> productDataOp = productDataList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getOrderNo()))).findFirst();
        if (null != productDataOp && productDataOp.isPresent()) {
            startDateTime = productDataOp.get().getCreateDatetime();
            log.info("Pcn生产数据RFID匹配JOB,获取到的生产数据中存在未保存成功的数据,第一个数据ID[{}]创建时间[{}]RFID[{}]",
                    productDataOp.get().getId(), startDateTime, productDataOp.get().getGroupNo());
        } else {
            log.info("Pcn生产数据RFID匹配JOB,获取到的生产数据全部保存成功");
            startDateTime = productDataList.get(productDataList.size() - 1).getCreateDatetime();
        }
        return startDateTime;
    }

    private List<String> saveProductData(List<MesProductData> productDataList, Map<String, MesProductDataRfidRecord> rfidRecordMap) {
        List<String> savedDataList = new ArrayList<>();
        for (MesProductData productData : productDataList) {
            if (null == productData) {
                continue;
            }
            saveItemProductData(productData, rfidRecordMap.get(productData.getGroupNo()), savedDataList);
        }
        return savedDataList;
    }

    private void saveItemProductData(MesProductData productData, MesProductDataRfidRecord rfidRecord, List<String> savedDataList) {
        if (null != rfidRecord) {
            productData.setSerialNumber(rfidRecord.getSerialNumber());
            productData.setProductSn(rfidRecord.getSerialNumber());
            productData.setOrderNo(rfidRecord.getWorkOrderNo());
            productData.setWorkCenterCode(rfidRecord.getWorkCenterCode());
            productData.setWorkCenterName(collectDbProductDataStepService.doGetCenterOrCellName(productData.getOrganizeCode(), productData.getWorkCenterCode(), null));
            productData.setWorkCellName(collectDbProductDataStepService.doGetCenterOrCellName(productData.getOrganizeCode(), productData.getWorkCenterCode(), productData.getWorkCellCode()));
            productData.setPartNo(rfidRecord.getPartNo());
            productData.setPartDesc(rfidRecord.getPartNameRdd());
            productData.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            ConvertBean.serviceModelUpdate(rfidRecord, MesPcnExtConstWords.JOB);
            productDataRepository.save(productData);
            savedDataList.add(new StringJoiner(MesPcnExtConstWords.AND).add(productData.getId().toString()).add(productData.getGroupNo()).toString());
        }
    }

    private Map<String, MesProductDataRfidRecord> getRfidRecordMap(String organizeCode, List<String> groupNoList) {
        List<String> groupNoListNotInDb = null;
        Map<String, MesProductDataRfidRecord> rfidRecordMap = null;
        for (String groupNo : groupNoList) {
            if (StringUtils.isEmpty(groupNo)) {
                continue;
            }
            MesProductDataRfidRecord rfidRecord = getProductDataRfidRecord(organizeCode, groupNo);
            if (null != rfidRecord) {
                if (CollectionUtils.isEmpty(rfidRecordMap)) {
                    rfidRecordMap = new HashMap<>();
                }
                rfidRecordMap.put(groupNo, rfidRecord);
            } else {
                if (CollectionUtils.isEmpty(groupNoListNotInDb)) {
                    groupNoListNotInDb = new ArrayList<>();
                }
                groupNoListNotInDb.add(groupNo);
            }
        }
        if (!CollectionUtils.isEmpty(groupNoListNotInDb)) {
            log.info("Pcn生产数据RFID匹配JOB,RFID匹配值[{}]未查询到采集数据RFID记录信息", groupNoListNotInDb.toString());
        }
        return rfidRecordMap;
    }

    private MesProductDataRfidRecord getProductDataRfidRecord(String organizeCode, String groupNo) {
        return productDataRfidRecordRepository.getByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.RFID_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), groupNo});
    }

    private List<String> getGroupNoList(List<MesProductData> productDataList) {
        return (productDataList
                .stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getGroupNo()))).map(MesProductData::getGroupNo).collect(Collectors.toList()))
                .stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
    }

    private List<MesProductData> getProductDataList(String organizeCode, String startDateTime) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getIsNull(MesPcnExtConstWords.SERIAL_NUMBER, packBean);
        DdlPreparedPack.timeBuilder(startDateTime, null, MesPcnExtConstWords.CREATE_DATE_TIME, packBean, true);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.CREATE_DATE_TIME}, packBean);
        return productDataRepository.findByHqlWhere(packBean);
    }

    private MesConfig getPdRfidMatchCfg(String organizeCode) {
        return configService.getMesConfigByCfgCode(MesPcnExtConstWords.EP_PD_RFID_MATCH_CFG, organizeCode);
    }

    private void packNewConfig(MesConfig config, String organizeCode) {
        config.setCfgCode(MesPcnExtConstWords.EP_PD_RFID_MATCH_CFG);
        config.setCfgName("EP生产数据采集RFID数据处理时间配置");
        config.setCfgValue(INITIAL_TIME);
        config.setCfgValueDesc("必须以yyyy-MM-dd HH:mm:ss的时间格式配置");
        config.setOrganizeCode(organizeCode);
    }


    private String doCalcStartDate(String startDateTime) throws Exception {
        DateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT);
        return TimeTool.timeCalc(sdf.parse(startDateTime), Calendar.MINUTE, -1, MesPcnExtConstWords.DATETIME_FORMAT);
    }

}
