package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.step;

import cn.estsh.i3plus.ext.mes.pcn.api.base.IBomExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IConsistencyAffirmRecordService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IWorkCenterExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.bu.IMesBusiConfigService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMissingPartService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IPackageExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ProduceSnExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkCenterExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkOrderExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkOrderInfoModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.ConvertBeanExt;
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.serviceimpl.base.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.LocaleUtil;
import cn.estsh.i3plus.mes.pcn.util.PojoAttrUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesBom;
import cn.estsh.i3plus.pojo.mes.model.AttrBean;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
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.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description : 工步业务-本体包装下线工步
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2019-07-11
 * @Modify:
 **/
@Slf4j
@Service("sxNoumenonPackageLineOffStepService")
public class SxNoumenonPackageLineOffStepService extends BaseStepService {

    @Autowired
    private IMissingPartService missingPartService;

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private MesErrorLineOffRepository errorLineOffRepository;

    @Autowired
    private MesErrorLineOffDetailRepository errorLineOffDetailRepository;

    @Autowired
    private IBomExtService bomExtService;

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private IConsistencyAffirmRecordService consistencyAffirmRecordService;

    @Autowired
    private IPackageExtService packageExtService;

    @Autowired
    private MesPackageExtRepository packageExtRepository;

    @Autowired
    private IProduceSnRepairService produceSnRepairService;

    @Autowired
    private MesProduceSnRepairRepository produceSnRepairRepository;

    @Autowired
    private IMesBusiConfigService busiConfigService;

    @Override
    public StepResult execute(StationRequestBean reqBean) {
        log.info("SxNoumenonPackageLineOffStepService[execute] 参数：{}", reqBean);

        StationResultBean resultBean = new StationResultBean();
        String err;

        if (StringUtils.isEmpty(reqBean.getOrganizeCode())) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "入参缺少工厂代码");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        if (StringUtils.isEmpty(reqBean.getWorkOrderNo())) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "入参缺少生产工单号");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        if (StringUtils.isEmpty(reqBean.getSerialNumber())) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "入参缺少产品条码");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        WorkCenterExtModel centerModel = (WorkCenterExtModel) reqBean.getDataMap().get(MesPcnExtConstWords.WORK_CENTER);
        if (null == centerModel || (StringUtils.isEmpty(centerModel.getShiftCode()) || StringUtils.isEmpty(centerModel.getWorkTime()))) {
            MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode());
            if (null == workCenterExt) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线代码[%s]无效"), reqBean.getWorkCenterCode());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                foundExThrowNoShowMsg();
            }
            if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线代码[%s]未启动班次"), reqBean.getWorkCenterCode());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                foundExThrowNoShowMsg();
            }
            centerModel = new WorkCenterExtModel();
            BeanUtils.copyProperties(workCenterExt, centerModel, MesPcnExtConstWords.ID);
            reqBean.getDataMap().put(MesPcnExtConstWords.WORK_CENTER, centerModel);
        }

        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(reqBean.getOrganizeCode(), reqBean.getSerialNumber());
        if (null == produceSnExt) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]无效"), reqBean.getSerialNumber());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), reqBean.getWorkOrderNo());
        if (null == workOrderExt) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产工单号[%s]无效"), reqBean.getWorkOrderNo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        String offLineTime = TimeTool.getNowTime(true);

        List<MesMissingPart> missingPartList = missingPartService.getMissingPartByWorkOrderNo(reqBean.getOrganizeCode(), reqBean.getWorkOrderNo());
        if (!CollectionUtils.isEmpty(missingPartList)) {
            List<String> itemPartNameList = missingPartList.stream().filter(o -> null != o).map(MesMissingPart::getItemPartName).collect(Collectors.toList());
            log.info("生产线[{}]工位[{}]产品条码[{}]存在缺件BOM:{},异常下线", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), reqBean.getSerialNumber(), itemPartNameList.toString());
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]存在缺件BOM,异常下线"), reqBean.getSerialNumber());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);

            refresh(reqBean, missingPartList);

            List<MesBom> bomList = bomExtService.getBomListByPartNo(reqBean.getOrganizeCode(), workOrderExt.getPartNo());
            Map<String, List<MesBom>> itemMap = CollectionUtils.isEmpty(bomList) ? null :
                    bomList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesBom::getItemPartNo));

            MesErrorLineOff errorLineOff = new MesErrorLineOff();
            errorLineOff.setSerialNumber(reqBean.getSerialNumber());
            errorLineOff.setWorkOrderNo(reqBean.getWorkOrderNo());
            errorLineOff.setPartNo(workOrderExt.getPartNo());
            errorLineOff.setPartName(workOrderExt.getPartNameRdd());
            errorLineOff.setWorkCenterCode(reqBean.getWorkCenterCode());
            errorLineOff.setWorkCellCode(reqBean.getWorkCellCode());
            errorLineOff.setOutWcTime(offLineTime);
            errorLineOff.setFreStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
            errorLineOff.setConfirmStatus(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
            errorLineOff.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            errorLineOff.setOrganizeCode(reqBean.getOrganizeCode());
            ConvertBean.serviceModelInitialize(errorLineOff, reqBean.getUserInfo());
            errorLineOff = errorLineOffRepository.insert(errorLineOff);

            for (MesMissingPart missingPart : missingPartList) {
                if (null == missingPart) {
                    continue;
                }
                MesErrorLineOffDetail errorLineOffDetail = new MesErrorLineOffDetail();
                errorLineOffDetail.setPid(errorLineOff.getId());
                errorLineOffDetail.setSerialNumber(reqBean.getSerialNumber());
                errorLineOffDetail.setWorkOrderNo(reqBean.getWorkOrderNo());
                errorLineOffDetail.setItemPartNo(missingPart.getItemPartNo());
                errorLineOffDetail.setItemPartName(missingPart.getItemPartName());
                errorLineOffDetail.setQty((!CollectionUtils.isEmpty(itemMap) && itemMap.containsKey(missingPart.getItemPartNo())) ?
                        itemMap.get(missingPart.getItemPartNo()).get(0).getQty() : new Double(0));
                errorLineOffDetail.setOrganizeCode(reqBean.getOrganizeCode());
                errorLineOffDetail.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
                ConvertBean.serviceModelInitialize(errorLineOffDetail, reqBean.getUserInfo());
                errorLineOffDetailRepository.insert(errorLineOffDetail);
            }

            workOrderExt.setMissingQty(MathOperation.add(workOrderExt.getMissingQty(), new Double(1)));
            produceSnExt.setSnStatus(MesPcnExtEnumUtil.PRODUCE_SN_STATUS.ERR_OFFLINE.getValue());
        } else {
            produceSnExt.setSnStatus(MesPcnExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue());
        }

        // 判断是否净水器线，从业务配置里面读取配置
        MesBusiConfig mesBusiConfig = busiConfigService.queryBusiConfigeByCfgCode(MesPcnExtConstWords.WATER_PURIFIER_CODE, reqBean.getOrganizeCode());

        boolean iswaterPurifierWorkCenter = false;
        if(mesBusiConfig != null && !StringUtils.isEmpty(mesBusiConfig.getCfgValue())){
            List<String> workCenterCodeList = Arrays.stream(mesBusiConfig.getCfgValue().split(MesPcnExtConstWords.COMMA)).collect(Collectors.toList());
            if(workCenterCodeList.contains(reqBean.getWorkCenterCode())) {
                iswaterPurifierWorkCenter = true;
            }
        }

        //若不是净水器线，则叠加完成数量,修改条码表中的ShiftCode、WorkTime、LotNo等信息
        if(!iswaterPurifierWorkCenter){
            workOrderExt.setCompleteQty(MathOperation.add(workOrderExt.getCompleteQty(), new Double(1)));
            if (MesPcnExtEnumUtil.PRODUCE_SN_TYPE.REMAKE_SN.getValue() == produceSnExt.getSnType())
                workOrderExt.setFiCompleteQty(StringUtils.isEmpty(workOrderExt.getFiCompleteQty()) ? new Double(1) : MathOperation.add(workOrderExt.getFiCompleteQty(), new Double(1)));
            ConvertBean.serviceModelUpdate(workOrderExt, reqBean.getUserInfo());
            workOrderExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            new ConvertBeanExt(workOrderExt).convertBean(workOrderExt);
            workOrderExtRepository.save(workOrderExt);

            if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != workOrderExt.getWorkOrderType()) {
                produceSnExt.setOutWorkCenterTime(offLineTime);
                produceSnExt.setShiftCode(centerModel.getShiftCode());
                produceSnExt.setWorkTime(centerModel.getWorkTime());
                produceSnExt.setLotNo(centerModel.getWorkTime());
                MesPackageExt packageExt = packageExtService.getPackageByPackNo(reqBean.getOrganizeCode(), reqBean.getPackageNo());
                if (null != packageExt && (StringUtils.isEmpty(packageExt.getLotNo()) || !packageExt.getLotNo().equals(produceSnExt.getLotNo()))) {
                    packageExt.setLotNo(produceSnExt.getLotNo());
                    packageExt.setWorkTime(produceSnExt.getWorkTime());
                    packageExt.setShiftCode(produceSnExt.getShiftCode());
                    ConvertBean.serviceModelUpdate(packageExt, reqBean.getUserInfo());
                    packageExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
                    new ConvertBeanExt(packageExt).convertBean(packageExt);
                    packageExtRepository.save(packageExt);
                }
            } else {
                MesProduceSnRepair produceSnRepair = produceSnRepairService.getProduceSnRepairBySnAndOrderNo(reqBean.getOrganizeCode(), produceSnExt.getSerialNumber(), reqBean.getWorkOrderNo());
                if (null == produceSnRepair) {
                    err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]未关联返工工单[%s]"), produceSnExt.getSerialNumber(), reqBean.getWorkOrderNo());
                    this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                    foundExThrowNoShowMsg();
                }
                produceSnRepair.setOutWorkCenterTime(offLineTime);
                produceSnRepair.setShiftCode(centerModel.getShiftCode());
                produceSnRepair.setWorkTime(centerModel.getWorkTime());
                produceSnRepair.setLotNo(centerModel.getWorkTime());
                produceSnRepair.setWorkCellCode(reqBean.getWorkCellCode());
                ConvertBean.serviceModelUpdate(produceSnRepair, reqBean.getUserInfo());
                produceSnRepair.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
                produceSnRepairRepository.save(produceSnRepair);
            }
          /*  produceSnExtService.packSnExtProcess(produceSnExt, reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());
            ConvertBean.serviceModelUpdate(produceSnExt, reqBean.getUserInfo());
            produceSnExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
            produceSnExtRepository.save(produceSnExt);*/

            try {
                WorkOrderInfoModel workOrderInfoModel = new WorkOrderInfoModel();
                workOrderInfoModel.setWorkOrderNo(reqBean.getWorkOrderNo());
                workOrderInfoModel.setWorkCenterCode(reqBean.getWorkCenterCode());
                workOrderInfoModel.setPartNo(reqBean.getPartNo());
                workOrderInfoModel.setCompleteQty(workOrderExt.getCompleteQty());
                workOrderInfoModel.setQty(workOrderExt.getQty());
                workOrderInfoModel.setOrganizeCode(reqBean.getOrganizeCode());
                workOrderInfoModel.setCreateUser(reqBean.getUserInfo());
                consistencyAffirmRecordService.insertConsistencyAffirmRecord(workOrderInfoModel);
            } catch (Exception e) {
                log.error("产品条码[{}]产生一致性确认记录执行失败", reqBean.getSerialNumber());
                err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产生一致性确认记录执行失败");
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            }
        }
        produceSnExtService.packSnExtProcess(produceSnExt, reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());
        ConvertBean.serviceModelUpdate(produceSnExt, reqBean.getUserInfo());
        produceSnExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
        produceSnExtRepository.save(produceSnExt);

        ProduceSnExtModel snModel = new ProduceSnExtModel();
        BeanUtils.copyProperties(produceSnExt, snModel, MesPcnExtConstWords.ID);
        snModel.setWorkCenterCode(reqBean.getWorkCenterCode());
        snModel.setWorkCellCode(reqBean.getWorkCellCode());
        reqBean.getDataMap().put(MesPcnExtConstWords.PRODUCE_SN, snModel);

        WorkOrderExtModel orderModel = new WorkOrderExtModel();
        BeanUtils.copyProperties(workOrderExt, orderModel, MesPcnExtConstWords.ID);
        reqBean.getDataMap().put(MesPcnExtConstWords.WORK_ORDER, orderModel);

        return StepResult.getSuccessComplete();
    }

    private void refresh(StationRequestBean reqBean, List<MesMissingPart> missingPartList) {
        List<AttrBean> attrBeanList = new ArrayList<>();
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ITEM_PART_NO, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "原材料物料编码"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ITEM_PART_NAME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "原材料物料名称"));

        StationResultBean resultBean = new StationResultBean();
        resultBean.setBusiType(MesPcnEnumUtil.STATION_BUSI_TYPE.STEP_CONTENT.getValue());
        resultBean.setDataType(MesPcnEnumUtil.STATION_DATA_TYPE.TABLE.getValue());
        resultBean.setResultList(missingPartList);
        resultBean.setDataAttrList(attrBeanList);
        this.sendMessage(reqBean, resultBean);
    }

}
