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.model.GenSerialNoModel;
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.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author wangjie
 * @version 1.0
 * @date 2021/1/13 9:28
 **/
@Slf4j
@Service
public class FristItemOrderService implements IWorkOrderStartService {

    @Autowired
    private MesWorkCenterExtRepository workCenterExtRepository;

    @Autowired
    private MesOrderRuleRepository orderRuleRepository;

    @Autowired
    private MesProcessCellRepository processCellRepository;

    @Autowired
    private MesProcessFirstItemRepository mesProcessFirstItemRDao;

    @Autowired
    private MesOrderJobRepository orderJobRepository;

    @Autowired
    private MesFirstOrderDetailRepository firstOrderDetailRepository;

    @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.WORK_ORDER_FIRST.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("Q管理生成单据:工单[%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("Q管理生成单据:工单[%s]生产线[%s]未启动班次", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }

            List<MesOrderRule> orderRuleList = orderRuleRepository.findByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED,
                            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_ORDER_TYPE.WORK_ORDER_FIRST.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("Q管理生成单据:工单[%s]未配置生产线代码[%s][工单创建][Q管理]班次为[%s]或班次为空的单据规则信息,请检查", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode(), workCenterExt.getShiftCode());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }

            List<MesProcessCell> processCellList = processCellRepository.findByProperty(
                    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()});
            Map<String, List<MesProcessCell>> processCodeMap = CollectionUtils.isEmpty(processCellList) ? null :
                    processCellList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getProcessCode()))).collect(Collectors.groupingBy(MesProcessCell::getProcessCode));
            if (CollectionUtils.isEmpty(processCodeMap)) {
                msg = String.format("Q管理生成单据:工单[%s]生产线代码[%s]未维护工序工位信息", workOrderExt.getOrderNo(), workOrderExt.getWorkCenterCode());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }
            List<String> processCodeList = new ArrayList<>(processCodeMap.keySet());

            DdlPackBean packBean = DdlPackBean.getDdlPackBean(workOrderExt.getOrganizeCode());
            DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.WORK_ORDER_FIRST.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("Q管理生成单据:工单[%s]已经生成过首检单", workOrderExt.getOrderNo());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }

            DdlPackBean packBean1 = DdlPackBean.getDdlPackBean(workOrderExt.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack(workOrderExt.getPartNo(), MesPcnExtConstWords.PART_NO, packBean1);
            DdlPreparedPack.getInPackList(processCodeList, MesPcnExtConstWords.PROCESS_CODE, packBean1);
            List<MesProcessFirstItem> processFirstItemList = mesProcessFirstItemRDao.findByHqlWhere(packBean1);
            if (CollectionUtils.isEmpty(processFirstItemList)) {
                msg = String.format("Q管理生成单据:工单[%s]物料编码[%s]与工序代码%s未配置Q管理项目信息,请检查", workOrderExt.getOrderNo(), workOrderExt.getPartNo(), processCodeList.toString());
                log.info(msg);
                checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
                return;
            }
            String orderNo = insertMesOrderJob(workOrderExt, workCenterExt, orderRuleOp.get().getTaskType(), userInfo, checkErrorLog);
            if (StringUtils.isEmpty(orderNo)) {
                return;
            }
            insertMesFirstOrderDetail(orderNo, processFirstItemList, processCodeMap, userInfo);
        } catch (Exception e) {
            checkErrorLogService.insertCheckErrorLog(checkErrorLog, e.getMessage(), userInfo);
            log.info(e.getMessage());
        }
    }


    private String insertMesOrderJob(MesWorkOrderExt workOrderExt, MesWorkCenterExt workCenterExt, Integer taskType, String userInfo, MesCheckErrorLog checkErrorLog){
        // 调用平台生成条码的方法
        List<String> orderNoList = getOrderNoByRuleCode(1,
                MesPcnExtConstWords.ORDER_NO_RULE, new GenSerialNoModel(), userInfo, workOrderExt.getOrganizeCode());
        if (CollectionUtils.isEmpty(orderNoList)) {
            String msg = String.format("Q管理生成单据:工单[%s]单据编号未生成成功", workOrderExt.getOrderNo());
            log.info(msg);
            checkErrorLogService.insertCheckErrorLog(checkErrorLog, msg, userInfo);
            return null;
        }
        MesOrderJob orderJob = new MesOrderJob();
        orderJob.setOrderType(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.WORK_ORDER_FIRST.getValue());
        orderJob.setTaskType(taskType);
        orderJob.setOrderNo(orderNoList.get(0));
        orderJob.setWorkCenterCode(workOrderExt.getWorkCenterCode());
        orderJob.setShiftCode(workCenterExt.getShiftCode());
        orderJob.setWorkOrderNo(workOrderExt.getOrderNo());
        orderJob.setOrderStatus(MesPcnExtEnumUtil.MES_ORJ_ORDER_STATUS.CREATE.getValue());
        orderJob.setWorkTime(workCenterExt.getWorkTime());
        orderJob.setOrderDate(TimeTool.getToday());
        orderJob.setGenerateTime(TimeTool.getNowTime(true));
        orderJob.setOrganizeCode(workOrderExt.getOrganizeCode());
        ConvertBean.serviceModelInitialize(orderJob, userInfo);
        orderJobRepository.insert(orderJob);
        return orderJob.getOrderNo();

    }

    private void insertMesFirstOrderDetail(String orderNo, List<MesProcessFirstItem> processFirstItemList, Map<String, List<MesProcessCell>> processCodeMap, String userInfo){
        for(MesProcessFirstItem processFirstItem : processFirstItemList){
            MesFirstOrderDetail firstOrderDetail = new MesFirstOrderDetail();
            BeanUtils.copyProperties(processFirstItem, firstOrderDetail, MesPcnExtConstWords.ID);
            firstOrderDetail.setOrderNo(orderNo);
            List<MesProcessCell> processCellList = processCodeMap.get(processFirstItem.getProcessCode());
            if (!CollectionUtils.isEmpty(processCellList)) {
                firstOrderDetail.setWorkCellCode(processCellList.get(0).getWorkCellCode());
                firstOrderDetail.setWorkCellName(processCellList.get(0).getWorkCellName());
                firstOrderDetail.setProcessName(processCellList.get(0).getProcessName());
            }
            firstOrderDetail.setIsTeamConfirm(MesPcnExtEnumUtil.SHIFT_GROUP_CHECK.NO.getValue());
            firstOrderDetail.setIsQualityConfirm(MesPcnExtEnumUtil.QUALITY_CHECK.NO.getValue());
            ConvertBean.serviceModelInitialize(firstOrderDetail, userInfo);
            firstOrderDetailRepository.insert(firstOrderDetail);
        }
    }

    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;
        }
    }

}
