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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
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.codemaker.SnowflakeIdMaker;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesProductionAssembly;
import cn.estsh.i3plus.pojo.mes.bean.MesProductionAssemblyUnique;
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 cn.estsh.i3plus.pojo.mes.repository.MesProductionAssemblyRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesProductionAssemblyUniqueRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderAssemblyRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import com.alibaba.fastjson.JSONObject;
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.*;
import java.util.stream.Collectors;

/**
 * @Description : 保存装配记录工步 【排序】【删除平行工位的装配件】
 * @Author : wangjie
 **/
@Slf4j
@Service("mesAssemblySaveSortStepService")
public class MesAssemblySaveSortStepService extends BaseStepService {

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private MesProductionAssemblyRepository productionAssemblyRepository;

    @Autowired
    private MesWorkOrderAssemblyRepository workOrderAssemblyRepository;

    @Autowired
    private MesProductionAssemblyUniqueRepository productionAssemblyUniqueRepository;

    @Autowired
    private SnowflakeIdMaker snowflakeIdMaker;

    @Autowired
    private IMesProduceSnExtService produceSnExtService;

    //保存排序线装配件
    public List<MesProdRuleContext> saveSortProductionAssembly(StationRequestBean reqBean, List<MesProdRuleContext> prodRuleContextList, List<MesProductionPsOutContext> productionPsOutContextList, MesScanMonitorContext scanMonitorContext) {

        Map<Integer, MesProductionPsOutContext> ppMap = CollectionUtils.isEmpty(productionPsOutContextList) ? null : productionPsOutContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.toMap(MesProductionPsOutContext::getForeignKey, o -> o));

        Long mouldRecordId = null != scanMonitorContext ? scanMonitorContext.getMouldRecordId() : null;

        List<Long> productSnIdList = new ArrayList<>();

        //获取模具号
        String mouldNo = getMouldNo(reqBean, prodRuleContextList);

        for (MesProdRuleContext prodRuleContext : prodRuleContextList) {

            if (null == prodRuleContext) continue;

            if (StringUtils.isEmpty(prodRuleContext.getAssemblyDataJson())) continue;

            //显示装配件的时候会进行赋值, 后续匹配的时候已经有值
            if (StringUtils.isEmpty(prodRuleContext.getProductionRecordId())) prodRuleContext.setProductionRecordId(snowflakeIdMaker.nextId());
            if (StringUtils.isEmpty(prodRuleContext.getMouldNo())) prodRuleContext.setMouldNo(mouldNo);

            MesProductionPsOutContext productionPsOutContext = CollectionUtils.isEmpty(ppMap) ? null : ppMap.get(prodRuleContext.getForeignKey());

            List<MesProductionAssemblySortContext> productionAssemblySortContextList = prodRuleContext.getSortAssemblyDataContext();

            for (MesProductionAssemblySortContext productionAssemblySortContext : productionAssemblySortContextList) {

                if (null == productionAssemblySortContext) continue;

                if (productionAssemblySortContext.getIsSaveDb().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) continue;

                if (productionAssemblySortContext.getAssemblyStatus().compareTo(MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_30.getValue()) == 0) continue;

                if (StringUtils.isEmpty(productionAssemblySortContext.getId())) {
                    MesProductionAssembly productionAssembly = new MesProductionAssembly();
                    BeanUtils.copyProperties(productionAssemblySortContext, productionAssembly);
                    productionAssembly.setIsOrigSn(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
                    if (null != productionPsOutContext) {
                        productionAssembly.setSerialNumber(productionPsOutContext.getSerialNumber());
                        productionAssembly.setCustSn(productionPsOutContext.getCustSn());
                    }
                    productionAssembly.setMouldRecordId(mouldRecordId);
                    productionAssembly.setProductionRecordId(prodRuleContext.getProductionRecordId());
                    productionAssembly.setMouldNo(mouldNo);
                    productionAssembly.setFid(UUID.randomUUID().toString());
                    productionAssembly.setOrganizeCode(reqBean.getOrganizeCode());
                    ConvertBean.serviceModelInitialize(productionAssembly, reqBean.getUserInfo());
                    productionAssembly.setRemark(getRemark(reqBean.getWorkCellCode(), productionAssemblySortContext.getWorkCellCode(), null));
                    productionAssembly = productionAssemblyRepository.insert(productionAssembly);

                    productionAssemblySortContext.setId(productionAssembly.getId());

                } else {

                    productionAssemblyRepository.updateByPropertiesNoSync(
                            new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE},
                            new Object[]{productionAssemblySortContext.getId(), reqBean.getOrganizeCode()},
                            new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS,
                                    MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.ASSEMBLY_STATUS, MesPcnExtConstWords.ASSEMBLY_SN,
                                    MesPcnExtConstWords.IS_SKIP, MesPcnExtConstWords.MOULD_NO, MesPcnExtConstWords.MOULD_RECORD_ID,
                                    MesPcnExtConstWords.PRODUCTION_RECORD_ID, MesPcnExtConstWords.REMARK},
                            new Object[]{reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                                    MesPcnExtConstWords.EMPTY, productionAssemblySortContext.getAssemblyStatus(), productionAssemblySortContext.getAssemblySn(),
                                    productionAssemblySortContext.getIsSkip(), mouldNo, mouldRecordId,
                                    prodRuleContext.getProductionRecordId(), getRemark(reqBean.getWorkCellCode(), productionAssemblySortContext.getWorkCellCode(), productionAssemblySortContext.getPaRemark())});

                }

                saveWorkOrderAssembly(reqBean, productionAssemblySortContext);

                productionAssemblySortContext.isSaveDb();

                saveProductionAssemblyUnique(reqBean, productionAssemblySortContext);

                if (!StringUtils.isEmpty(productionAssemblySortContext.getProductSnId())) productSnIdList.add(productionAssemblySortContext.getProductSnId());

            }

            prodRuleContext.assemblyDataJson(productionAssemblySortContextList);

        }

        if (!CollectionUtils.isEmpty(productSnIdList)) produceSnExtService.saveProduceSnList(reqBean, MesExtEnumUtil.PRODUCE_SN_STATUS.ASSEMBLY.getValue(), productSnIdList);

        return prodRuleContextList;

    }

    private String getMouldNo(StationRequestBean reqBean, List<MesProdRuleContext> prodRuleContextList) {
        Optional<MesProdRuleContext> optional = prodRuleContextList.stream().filter(o -> null != o && !StringUtils.isEmpty(o.getMouldNo())).findFirst();
        if (null != optional && optional.isPresent()) return optional.get().getMouldNo();
        MesEquipVariableCollectContext equipVariableCollectContext = productionDispatchContextStepService.getMouldNoContext(reqBean);
        return null != equipVariableCollectContext ? equipVariableCollectContext.getEquipVariableValue() : null;
    }

    private String getRemark(String curWorkCellCode, String workCellCode, String remark) {
        if (curWorkCellCode.equals(workCellCode)) return remark;
        StringJoiner sj = new StringJoiner(MesPcnExtConstWords.SEMICOLON);
        if (!StringUtils.isEmpty(remark)) sj.add(remark);
        return sj.add(String.format("装配工位[%s]", curWorkCellCode)).toString();
    }

    private void saveProductionAssemblyUnique(StationRequestBean reqBean, MesProductionAssemblySortContext productionAssemblySortContext) {
        if (!MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.checkUniqueRuleInDb(productionAssemblySortContext.getMatchType()) || StringUtils.isEmpty(productionAssemblySortContext.getAssemblySn())) return;
        MesProductionAssemblyUnique productionAssemblyUnique = new MesProductionAssemblyUnique();
        BeanUtils.copyProperties(productionAssemblySortContext, productionAssemblyUnique, MesPcnExtConstWords.ID);
        productionAssemblyUnique.setPid(productionAssemblySortContext.getId());
        productionAssemblyUnique.setOrganizeCode(reqBean.getOrganizeCode());
        ConvertBean.serviceModelInitialize(productionAssemblyUnique, reqBean.getUserInfo());
        productionAssemblyUniqueRepository.insert(productionAssemblyUnique);
    }

    private void saveWorkOrderAssembly(StationRequestBean reqBean, MesProductionAssemblySortContext productionAssemblySortContext) {
        workOrderAssemblyRepository.updateByPropertiesNoSync(
                new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE},
                new Object[]{productionAssemblySortContext.getSourceId(), reqBean.getOrganizeCode()},
                new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS,
                        MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.ASSEMBLY_STATUS, MesPcnExtConstWords.REMARK},
                new Object[]{reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                        MesPcnExtConstWords.EMPTY, productionAssemblySortContext.getAssemblyStatus(),
                        getRemark(reqBean.getWorkCellCode(), productionAssemblySortContext.getWorkCellCode(), productionAssemblySortContext.getWoaRemark())});
    }

    //删除平行工位的装配件
    public void deleteSortWorkOrderAssembly(StationRequestBean reqBean, MesProdRuleContext prodRuleContext) {

        if (StringUtils.isEmpty(prodRuleContext.getParallelInfo())) return;

        Map<String, Object> parallelInfoMap = JSONObject.parseObject(prodRuleContext.getParallelInfo(), Map.class);

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(prodRuleContext.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        DdlPreparedPack.getStringEqualPack(prodRuleContext.getProductSn(), MesPcnExtConstWords.PRODUCT_SN, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_30.getValue(), MesPcnExtConstWords.ASSEMBLY_STATUS, packBean);

        if (parallelInfoMap.containsKey(MesPcnExtConstWords.WORK_CELL_CODE)) {

            List<String> workCellCodeList = (List<String>) parallelInfoMap.get(MesPcnExtConstWords.WORK_CELL_CODE);

            if (workCellCodeList.size() == 1) DdlPreparedPack.getStringEqualPack(workCellCodeList.get(0), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
            else DdlPreparedPack.getInPackList(workCellCodeList, MesPcnExtConstWords.WORK_CELL_CODE, packBean);

        } else {

            Integer processSeq = (Integer) parallelInfoMap.get(MesPcnExtConstWords.PROCESS_SEQ);

            DdlPreparedPack.getStringEqualPack(prodRuleContext.getCraftCode(), MesPcnExtConstWords.CRAFT_CODE, packBean);
            DdlPreparedPack.getNumEqualPack(processSeq, MesPcnExtConstWords.PROCESS_SEQ, packBean);
            DdlPreparedPack.getNumNOEqualPack(prodRuleContext.getWorkCellCode(), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        }

        int count = workOrderAssemblyRepository.updateByPropertiesNoSync(
                new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS,
                        MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.REMARK},
                new Object[]{reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                        MesPcnExtConstWords.EMPTY, CommonEnumUtil.IS_VAILD.INVAILD.getValue(), String.format("平行工位[%s]标记无效!", reqBean.getWorkCellCode())},
                packBean);

        this.sendMessage(reqBean, new StationResultBean().writeDbLog(), String.format("加工单[%s]在工位[%s]标记平行工位的装配件条数[%s]",
                prodRuleContext.getWorkOrderNo(), reqBean.getWorkCellCode(), count), MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);

    }

    //删除平行工位的装配件
    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

        StepResult stepResult = StepResult.getSuccessComplete();

        //获取上下文信息
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean);

        //配置错误 抛出异常
        if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());

        //存储生产过程上下文对象
        productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext);

        //获取上下文产品加工规则数据信息集合
        List<MesProdRuleContext> prodRuleContextList = productionDispatchContextStepService.getProdRuleDataContext(reqBean);

        if (CollectionUtils.isEmpty(prodRuleContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在非排序加工规则数据,请重置工序!");

        for (MesProdRuleContext prodRuleContext : prodRuleContextList) {
            if (null == prodRuleContext || StringUtils.isEmpty(prodRuleContext.getAssemblyDataJson())) continue;
            List<MesProductionAssemblySortContext> productionAssemblySortContextList = prodRuleContext.getSortAssemblyDataContext();
            int count = workOrderAssemblyRepository.updateByPropertiesNoSync(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.WORK_ORDER_NO, MesPcnExtConstWords.CRAFT_CODE, MesPcnExtConstWords.PROCESS_SEQ, MesPcnExtConstWords.ASSEMBLY_STATUS},
                    new Object[]{reqBean.getOrganizeCode(), prodRuleContext.getWorkOrderNo(), productionProcessContext.getCraftCode(), productionAssemblySortContextList.get(0).getProcessSeq(), MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_30.getValue()},
                    new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS,
                            MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.REMARK},
                    new Object[]{reqBean.getUserInfo(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                            MesPcnExtConstWords.EMPTY, CommonEnumUtil.IS_VAILD.INVAILD.getValue(), String.format("平行工位[%s]标记无效!", reqBean.getWorkCellCode())});
            this.sendMessage(reqBean, resultBean.writeDbLog(), String.format("加工单[%s]在工位[%s]标记平行工位的装配件条数[%s]",
                    prodRuleContext.getWorkOrderNo(), reqBean.getWorkCellCode(), count), MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        }

        return stepResult;

    }

}
