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

import cn.estsh.i3plus.ext.mes.pcn.api.base.ICheckErrorLogService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IWorkOrderStartService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
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.busi.ISyncFuncService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.BaseResultBean;
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.MesWorkCell;
import cn.estsh.i3plus.pojo.mes.model.GenSerialNoModel;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkCellRepository;
import cn.estsh.i3plus.pojo.mes.sqlpack.MesHqlPack;
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.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Author: xiangming.liao
 * @CreateDate: 2021/02/01 16:33
 * @Description:
 **/
@Slf4j
@Service
public class CreatePartCheckService implements IWorkOrderStartService {
    @Autowired
    private MesPartCheckDetailRepository partCheckDetailRepository;
    @Autowired
    private MesOrderRuleRepository orderRuleRepository;
    @Autowired
    private MesOrderJobRepository orderJobRepository;
    @Autowired
    private MesProcessBomRepository processBomRepository;
    @Autowired
    private MesProcessCellRepository processCellRepository;
    @Autowired
    private MesWorkCellRepository workCellRepository;
    @Autowired
    private MesWorkCenterExtRepository workCenterExtRepository;
    @Autowired
    private ISyncFuncService syncFuncService;
    @Autowired
    private ICheckErrorLogService checkErrorLogService;

    @Override
    public void doGenCheckOrder(MesWorkOrderExt workOrderExt, String userInfo) {
        MesCheckErrorLog checkErrorLog = new MesCheckErrorLog();
        checkErrorLog.setGenerationMethod(MesPcnExtEnumUtil.GENERATION_METHOD.FROM_WORK_ORDER_START.getValue());
        checkErrorLog.setGeneratingModule(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.PART_CHECK.getDescription());

        String msg;
        try {
            MesWorkCenterExt workCenterExt = workCenterExtRepository.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.WORK_CENTER_CODE},
                    new Object[]{workOrderExt.getOrganizeCode(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), workOrderExt.getWorkCenterCode()});
            if (null == workCenterExt) {
                msg = String.format("物料点检生成单据:工单[%s]生产线[%s]无效", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }
            if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
                msg = String.format("物料点检生成单据:工单[%s]生产线[%s]未启动班次", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }

            DdlPackBean packBean = DdlPackBean.getDdlPackBean(workOrderExt.getOrganizeCode());
            DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.PART_CHECK.getValue(), MesPcnExtConstWords.ORDER_TYPE, packBean);
            DdlPreparedPack.getStringEqualPack(workOrderExt.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
            DdlPreparedPack.getStringEqualPack(workCenterExt.getShiftCode(), MesPcnExtConstWords.SHIFT_CODE, packBean);
            DdlPreparedPack.getStringEqualPack(workCenterExt.getWorkTime(), MesPcnExtConstWords.WORK_TIME, packBean);
            DdlPreparedPack.getStringEqualPack(workOrderExt.getOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
            List<MesOrderJob> orderJobList = orderJobRepository.findByHqlWhere(packBean);
            if (!CollectionUtils.isEmpty(orderJobList)) {
                msg = String.format("物料点检生成单据:工单[%s]已经生成过物料点检单", workOrderExt.getOrderNo());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }

            //1、查找产线下所有的工位
            List<MesWorkCell> mesWorkCellList = workCellRepository.findByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.WORK_CENTER_CODE},
                    new Object[]{workOrderExt.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), MesPcnExtEnumUtil.IS_VAILD.VAILD.getValue(), workOrderExt.getWorkCenterCode()});
            //2、通过产线和工位去工序工位关系表中查询所有的工序
            List<String> workCells = mesWorkCellList.stream().map(MesWorkCell::getWorkCellCode).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(workCells)) {
                msg = String.format("物料点检生成单据:工单[%s]生产线[%s]未关联工位", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }
            DdlPackBean pcPackBean = MesHqlPack.getMesAllData(workOrderExt.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack(workOrderExt.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, pcPackBean);
            DdlPreparedPack.getInPackList(workCells, MesPcnExtConstWords.WORK_CELL_CODE, pcPackBean);
            List<MesProcessCell> processCellList = processCellRepository.findByHqlWhere(pcPackBean);
            if (CollectionUtils.isEmpty(processCellList)) {
                msg = String.format("物料点检生成单据:工单[%s]请先维护工序工位关系", workOrderExt.getOrderNo());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }
            List<String> processs = processCellList.stream().map(MesProcessCell::getProcessCode).collect(Collectors.toList());
            //3、通过工序和物料号查询工序BOM
            DdlPackBean bomPackBean = MesHqlPack.getMesAllData(workOrderExt.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack(workOrderExt.getPartNo(), MesPcnExtConstWords.PART_NO, bomPackBean);
            DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_IS_BIND_KEY.NO_BIND_KEY.getValue(), MesPcnExtConstWords.IS_BIND_KEY, bomPackBean);
            DdlPreparedPack.getInPackList(processs, MesPcnExtConstWords.PROCESS_CODE, bomPackBean);
            List<MesProcessBom> processBoms = processBomRepository.findByHqlWhere(bomPackBean);
            if (CollectionUtils.isEmpty(processBoms)) {
                msg = String.format("物料点检生成单据:工单[%s]请先维护工序BOM", workOrderExt.getOrderNo());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }
            //4、生成单据作业
            MesOrderJob mesOrderJob = createOrderJob(workOrderExt, workCenterExt, userInfo, checkErrorLog);
            if (null == mesOrderJob) {
                return;
            }

            //5、生成物料点检详情
            List<MesPartCheckDetail> mesPartCheckDetails = new ArrayList<>();
            processBoms.forEach(pbom -> {
                MesPartCheckDetail dataModel = new MesPartCheckDetail();
                dataModel.setOrderNo(mesOrderJob.getOrderNo());
                dataModel.setWorkOrderNo(mesOrderJob.getWorkOrderNo());
                dataModel.setOrderDate(TimeTool.getToday());
                dataModel.setWorkCenterCode(mesOrderJob.getWorkCenterCode());
                dataModel.setProcessCode(pbom.getProcessCode());
                dataModel.setProcessName(pbom.getProcessName());
                dataModel.setShiftCode(mesOrderJob.getShiftCode());
                //通过工序和产线查询工序工位信息
                DdlPackBean pcPackBeanByPrcs = MesHqlPack.getMesAllData(workOrderExt.getOrganizeCode());
                DdlPreparedPack.getStringEqualPack(pbom.getProcessCode(), MesPcnExtConstWords.PROCESS_CODE, pcPackBeanByPrcs);
                DdlPreparedPack.getStringEqualPack(mesOrderJob.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, pcPackBeanByPrcs);
                MesProcessCell processCell = processCellRepository.getByProperty(pcPackBeanByPrcs);
                dataModel.setWorkCellCode(null == processCell ? null : processCell.getWorkCellCode());
                dataModel.setPartNo(pbom.getPartNo());
                dataModel.setPartNameRdd(pbom.getPartNameRdd());
                dataModel.setItemPartNo(pbom.getItemPartNo());
                dataModel.setItemPartName(pbom.getItemPartName());
                dataModel.setOrderStatus(MesPcnExtEnumUtil.MES_ORJ_ORDER_STATUS.CREATE.getValue());
                dataModel.setShiftGroupCheck(MesPcnExtEnumUtil.SHIFT_GROUP_CHECK.NO.getValue());
                dataModel.setQualityCheck(MesPcnExtEnumUtil.QUALITY_CHECK.NO.getValue());
                dataModel.setOrganizeCode(workOrderExt.getOrganizeCode());
                dataModel.setGenerateTime(TimeTool.getNowTime(true));
                ConvertBean.serviceModelInitialize(dataModel, userInfo);
                partCheckDetailRepository.insert(dataModel);
                mesPartCheckDetails.add(dataModel);
            });
            List<String> collect = (mesPartCheckDetails.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkCellCode())))
                    .map(MesPartCheckDetail::getWorkCellCode).collect(Collectors.toList()))
                    .stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
            String cellCollect = org.apache.commons.lang.StringUtils.join(collect, MesPcnExtConstWords.COMMA);
            mesOrderJob.setCellCollect(cellCollect);

            orderJobRepository.insert(mesOrderJob);
        } catch (Exception e) {
            checkErrorLogService.insertCheckErrorLog(checkErrorLog, e.getMessage(), userInfo);
            log.info(e.getMessage());
        }
    }

    private MesOrderJob createOrderJob(MesWorkOrderExt workOrderExt, MesWorkCenterExt workCenterExt, String userInfo, MesCheckErrorLog checkErrorLog) {
        String msg;
        List<MesOrderRule> orderRuleList = orderRuleRepository.findByProperty(
        new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED,
                MesPcnExtConstWords.TASK_TYPE, MesPcnExtConstWords.ORDER_TYPE, MesPcnExtConstWords.CREATE_RULE, MesPcnExtConstWords.WORK_CENTER_CODE},
        new Object[]{workOrderExt.getOrganizeCode(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                MesPcnExtEnumUtil.MES_OR_TASK_TYPE.PREPARE_TASK.getValue(), MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.PART_CHECK.getValue(),
                MesPcnExtEnumUtil.MES_OR_CREATE_RULE.WORK_ORDER_CREATE.getValue(), workOrderExt.getWorkCenterCode()});
        Optional<MesOrderRule> orderRuleOp = CollectionUtils.isEmpty(orderRuleList) ? null :
                orderRuleList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getShiftCode()) && o.getShiftCode().equals(workCenterExt.getShiftCode()))).findFirst();
        if (null == orderRuleOp || !orderRuleOp.isPresent()) {
            orderRuleOp = CollectionUtils.isEmpty(orderRuleList) ? null : orderRuleList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getShiftCode()))).findFirst();
        }
        if (null == orderRuleOp || !orderRuleOp.isPresent()) {
            msg = String.format("物料点检生成单据:工单[%s]未配置生产线代码[%s][准备作业][工单创建][物料点检]班次为[%s]或班次为空的单据规则信息,请检查", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode(), workCenterExt.getShiftCode());
            log.info(msg);
            checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
            return null;
        }

        //组装数据
        MesOrderJob mesOrderJob = new MesOrderJob();
        mesOrderJob.setWorkOrderNo(workOrderExt.getOrderNo());
        mesOrderJob.setTaskType(MesPcnExtEnumUtil.MES_OR_TASK_TYPE.PREPARE_TASK.getValue());
        mesOrderJob.setOrderType(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.PART_CHECK.getValue());
        //设置单据编号 调用平台生成条码的方法
        List<String> orderNoList = getOrderNoByRuleCode(1, MesPcnExtConstWords.ORDER_NO_RULE, new GenSerialNoModel(), userInfo, workOrderExt.getOrganizeCode());
        if (CollectionUtils.isEmpty(orderNoList)) {
            msg = String.format("物料点检生成单据:工单[%s]单据编号未生成成功", workOrderExt.getOrderNo());
            log.info(msg);
            checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
            return null;
        }
        mesOrderJob.setOrderNo(orderNoList.get(0));
        mesOrderJob.setOrderStatus(MesPcnExtEnumUtil.MES_ORJ_ORDER_STATUS.CREATE.getValue());
        mesOrderJob.setOrderDate(TimeTool.getToday());
        mesOrderJob.setWorkTime(workCenterExt.getWorkTime());
        mesOrderJob.setShiftCode(workCenterExt.getShiftCode());
        mesOrderJob.setWorkCenterCode(workOrderExt.getWorkCenterCode());
        mesOrderJob.setOrganizeCode(workOrderExt.getOrganizeCode());
        ConvertBean.serviceModelInitialize(mesOrderJob, userInfo);
        mesOrderJob.setGenerateTime(mesOrderJob.getModifyDatetime());
        return mesOrderJob;
    }

    /**
     * 生成单据编号
     * @param number
     * @param ruleCode
     * @param genSerialNoModel
     * @param userName
     * @param org
     * @return
     */
    public List<String> getOrderNoByRuleCode(int number, String ruleCode, GenSerialNoModel genSerialNoModel, String userName, String org) {
        genSerialNoModel.setRuleCode(ruleCode);
        BaseResultBean<String> serialNumberBean;
        try {
            serialNumberBean = syncFuncService.syncSerialNo(genSerialNoModel, userName, org, Integer.valueOf(number));
        } catch (Exception e) {
            return null;
        }
        if (serialNumberBean != null && serialNumberBean.isSuccess()) {
            return serialNumberBean.getResultList();
        } else {
            return null;
        }
    }
}
