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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IWorkCenterExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.job.IEquipmentCheckOrderService;
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.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.Calendar;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: wangjie
 * @CreateDate: 2019/8/23 1:16 PM
 * @Description: Pcn处理工单自动批量生成条码
 **/
@Slf4j
@Service
public class EquipmentCheckOrderService implements IEquipmentCheckOrderService {

    @Autowired
    private MesEquipmentCheckRepository equipmentCheckRepository;

    @Autowired
    private MesOrderRuleRepository orderRuleRepository;

    @Autowired
    private MesOrderJobRepository orderJobRepository;

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private MesEquipmentCheckDetailRepository equipmentCheckDetailRepository;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private ISyncFuncService syncFuncService;


    @Override
    public void doHandleEquipmentCheckOrder(String organizeCode) {
        List<String> checkTypeList = getCheckTypelist();

        for (String checkType : checkTypeList) {
            if (StringUtils.isEmpty(checkType)) {
                continue;
            }
            Boolean isSuccess = false;
            List<MesEquipmentCheck> equipmentCheckList = getEquipmentCheckList(organizeCode, checkType);
            if (CollectionUtils.isEmpty(equipmentCheckList)) {
                log.info("Pcn处理设备点检单据生成JOB,未配置[{}]类型的设备点检项目",
                        MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType));
                continue;
            }
            List<String> workCenterCodeList = (equipmentCheckList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkCenterCode())))
                    .map(MesEquipmentCheck::getWorkCenterCode).collect(Collectors.toList()))
                    .stream().filter(o -> !StringUtils.isEmpty(o)).distinct().collect(Collectors.toList());
            log.info("Pcn处理设备点检单据生成JOB,[{}]类型的设备点检单据生成包含以下生产线{}",
                    MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), workCenterCodeList.toString());
            for (String workCenterCode : workCenterCodeList) {
                if (StringUtils.isEmpty(workCenterCode)) {
                    continue;
                }
                List<MesOrderRule> orderRuleList = getOrderRuleList(organizeCode, workCenterCode, checkType);
                if (CollectionUtils.isEmpty(orderRuleList)) {
                    log.info("Pcn处理设备点检单据生成JOB,[{}]类型的设备点检单据生成,生产线[{}]未配置单据规则",
                            MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), workCenterCode);
                    continue;
                }

                List<MesWorkOrderExt> workOrderExtList = null;
                if (checkType.equals(MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.DAY_CHECK.getValue())) {
                    workOrderExtList = findWorkOrderList(organizeCode, workCenterCode);
                }

                for (MesOrderRule orderRule : orderRuleList) {
                    if (null == orderRule || StringUtils.isEmpty(orderRule.getProduceTime())) {
                        continue;
                    }
                    Boolean flag = false;
                    String produceTime = orderRule.getProduceTime() + MesPcnExtConstWords.APPEND_SECONDS;
                    String shiftCode = getCurShiftCode(orderRule.getShiftCode(), organizeCode, workCenterCode);
                    if (StringUtils.isEmpty(shiftCode)) {
                        log.info("Pcn处理设备点检单据生成JOB,生产线[{}]设备点检单据存在生成时间[{}]的单据未配置班次或生产线未启动班次", workCenterCode, produceTime);
                        continue;
                    }
                    if (checkType.equals(MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.DAY_CHECK.getValue())) {
                        if (TimeTool.stringParseToDate(TimeTool.getNowTime(MesPcnExtConstWords.TIME_FORMAT)).compareTo(TimeTool.stringParseToDate(produceTime)) >= 0) {
                            List<MesOrderJob> orderJobList = getOrderJobList(organizeCode, workCenterCode, shiftCode, checkType, produceTime);
                            if (CollectionUtils.isEmpty(orderJobList)) {
                                log.info("Pcn处理设备点检单据生成JOB,生产线[{}]还未生成类型[{}]生成时间[{}]班次[{}]的设备点检单据",
                                        workCenterCode, MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), produceTime, shiftCode);
                                if (CollectionUtils.isEmpty(workOrderExtList)) {
                                    log.info("Pcn处理设备点检单据生成JOB,生产线[{}]还未生成类型[{}]生成时间[{}]班次[{}]的设备点检单据,但未查询到启动或下达的工单",
                                            workCenterCode, MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), produceTime, shiftCode);
                                    continue;
                                }
                                flag = true;
                            }
                        }
                    } else {
                        List<MesOrderJob> orderJobList = getOrderJobList(organizeCode, workCenterCode, shiftCode, checkType, produceTime);
                        if (CollectionUtils.isEmpty(orderJobList)) {
                            log.info("Pcn处理设备点检单据生成JOB,生产线[{}]还未生成类型[{}]生成时间[{}]班次[{}]的设备点检单据",
                                    workCenterCode, MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), produceTime, shiftCode);
                            flag = true;
                        }
                    }

                    if (flag) {
                        log.info("Pcn处理设备点检单据生成JOB,生产线[{}]正在生成类型[{}]生成时间[{}]班次[{}]的设备点检单据",
                                workCenterCode, MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), produceTime, shiftCode);
                        String orderNo = getOrderNo(organizeCode);
                        if (StringUtils.isEmpty(orderNo)) {
                            log.info("Pcn处理设备点检单据生成JOB,生产线[{}]生成类型[{}]生成时间[{}]班次[{}]的设备点检单据时生成单据号失败",
                                    workCenterCode, MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType), produceTime, shiftCode);
                            continue;
                        }
                        insertEquipmentCheckOrder(organizeCode, workCenterCode, shiftCode, checkType, produceTime, orderNo,
                                equipmentCheckList.stream().filter(o -> (null != o && o.getWorkCenterCode().equals(workCenterCode))).collect(Collectors.toList()));
                        isSuccess = true;
                    }
                }
            }

            if (isSuccess) {
                log.info("Pcn处理设备点检单据生成JOB,[{}]类型的设备点检单据生成成功",
                        MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.valueOfDescription(checkType));
                break;
            }
        }
    }

    private String getCurShiftCode(String shiftCode, String organizeCode, String workCenterCode) {
        if (StringUtils.isEmpty(shiftCode)) {
            MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(organizeCode, workCenterCode);
            if (null != workCenterExt) {
                shiftCode = workCenterExt.getShiftCode();
            }
        }
        return shiftCode;
    }

    private void insertEquipmentCheckOrder(String organizeCode, String workCenterCode, String shiftCode, String checkType, String produceTime, String orderNo, List<MesEquipmentCheck> equipmentCheckList) {
        MesOrderJob orderJob = new MesOrderJob();
        orderJob.setTaskType(MesPcnExtEnumUtil.MES_OR_TASK_TYPE.PREPARE_TASK.getValue());
        orderJob.setOrderType(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.EQU_CHECK.getValue());
        orderJob.setHandlerMethod(MesPcnExtEnumUtil.HANDLER_METHOD.AUTOMATICALLY_CREATED.getValue());
        orderJob.setOrderNo(orderNo);
        orderJob.setWorkCenterCode(workCenterCode);
        orderJob.setOrderStatus(MesPcnExtEnumUtil.MES_ORJ_ORDER_STATUS.CREATE.getValue());
        orderJob.setOrderDate(TimeTool.getToday());
        orderJob.setWorkTime(orderJob.getOrderDate());
        orderJob.setGenerateTime(orderJob.getOrderDate() + MesPcnExtConstWords.ONE_SPACE + produceTime);
        orderJob.setCheckType(checkType);
        orderJob.setShiftCode(shiftCode);
        List<String> collect = (equipmentCheckList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkCellCode())))
                .map(MesEquipmentCheck::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);
        orderJob.setCellCollect(cellCollect);
        orderJob.setOrganizeCode(organizeCode);
        ConvertBean.serviceModelInitialize(orderJob, MesPcnExtConstWords.JOB);
        orderJobRepository.insert(orderJob);

        for (MesEquipmentCheck equipmentCheck : equipmentCheckList) {
            MesEquipmentCheckDetail equipmentCheckDetail = new MesEquipmentCheckDetail();
            BeanUtils.copyProperties(equipmentCheck, equipmentCheckDetail, MesPcnExtConstWords.ID);
            equipmentCheckDetail.setOrderJobNo(orderNo);
            equipmentCheckDetail.setCheckType(checkType);
            equipmentCheckDetail.setShiftCode(shiftCode);
            equipmentCheckDetail.setIsTeamConfirm(MesPcnExtEnumUtil.SHIFT_GROUP_CHECK.NO.getValue());
            equipmentCheckDetail.setIsQualityConfirm(MesPcnExtEnumUtil.QUALITY_CHECK.NO.getValue());
            equipmentCheckDetail.setOrganizeCode(organizeCode);
            ConvertBean.serviceModelInitialize(equipmentCheckDetail, MesPcnExtConstWords.JOB);
            equipmentCheckDetailRepository.insert(equipmentCheckDetail);
        }
    }

    private String getOrderNo(String organizeCode) {
        String orderNo = null;
        try {
            BaseResultBean oneCodeResult = syncFuncService.syncSerialNo(new GenSerialNoModel(MesPcnExtConstWords.ORDER_NO_RULE), null, organizeCode, 1);
            if (oneCodeResult != null && oneCodeResult.isSuccess()) {
                orderNo = oneCodeResult.getResultList().get(0).toString();
            }
        } catch (Exception e) {
        }
        return orderNo;
    }

    private List<MesWorkOrderExt> findWorkOrderList(String organizeCode, String workCenterCode) {
        List<MesWorkOrderExt> workOrderExtList = null;
        List<MesWorkOrderExt> openList = getWorkOrderList(organizeCode, workCenterCode, MesPcnExtEnumUtil.WORK_ORDER_STATUS.OPEN.getValue());
        List<MesWorkOrderExt> landedList = getWorkOrderList(organizeCode, workCenterCode, MesPcnExtEnumUtil.WORK_ORDER_STATUS.LANDED.getValue());
        if (!CollectionUtils.isEmpty(openList) || !CollectionUtils.isEmpty(landedList)) {
            workOrderExtList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(openList)) {
                workOrderExtList.addAll(openList);
            }
            if (!CollectionUtils.isEmpty(landedList)) {
                workOrderExtList.addAll(landedList);
            }
        }
        return workOrderExtList;
    }

    private List<MesWorkOrderExt> getWorkOrderList(String organizeCode, String workCenterCode, Integer workOrderStatus) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(workOrderStatus, MesPcnExtConstWords.WORK_ORDER_STATUS, packBean);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        return workOrderExtRepository.findByHqlWhere(packBean);
    }

    private List<MesOrderJob> getOrderJobList(String organizeCode, String workCenterCode, String shiftCode, String checkType, String produceTime) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_TASK_TYPE.PREPARE_TASK.getValue(), MesPcnExtConstWords.TASK_TYPE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.EQU_CHECK.getValue(), MesPcnExtConstWords.ORDER_TYPE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.HANDLER_METHOD.AUTOMATICALLY_CREATED.getValue(), MesPcnExtConstWords.HANDLER_METHOD, packBean);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(shiftCode, MesPcnExtConstWords.SHIFT_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(checkType, MesPcnExtConstWords.CHECK_TYPE, packBean);
        String nowProduceTime = TimeTool.getToday() + MesPcnExtConstWords.ONE_SPACE + produceTime;
        String lastProduceTime;
        if (checkType.equals(MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.DAY_CHECK.getValue())) {
            DdlPreparedPack.getStringEqualPack(nowProduceTime, MesPcnExtConstWords.GENERATE_TIME, packBean);
        } else if (checkType.equals(MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.WEEK_CHECK.getValue())) {
            lastProduceTime = TimeTool.timeCalc(TimeTool.stringParseToDate(nowProduceTime), Calendar.DAY_OF_YEAR, -7, MesPcnExtConstWords.DATETIME_FORMAT);
            DdlPreparedPack.timeBuilder(lastProduceTime, nowProduceTime, MesPcnExtConstWords.GENERATE_TIME, packBean, true);
        } else if (checkType.equals(MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.MONTH_CHECK.getValue())) {
            lastProduceTime = TimeTool.timeCalc(TimeTool.stringParseToDate(nowProduceTime), Calendar.DAY_OF_YEAR, -30, MesPcnExtConstWords.DATETIME_FORMAT);
            DdlPreparedPack.timeBuilder(lastProduceTime, nowProduceTime, MesPcnExtConstWords.GENERATE_TIME, packBean, true);
        } else {
            lastProduceTime = TimeTool.timeCalc(TimeTool.stringParseToDate(nowProduceTime), Calendar.YEAR, -1, MesPcnExtConstWords.DATETIME_FORMAT);
            DdlPreparedPack.timeBuilder(lastProduceTime, nowProduceTime, MesPcnExtConstWords.GENERATE_TIME, packBean, true);
        }
        return orderJobRepository.findByHqlWhere(packBean);
    }

    private List<MesOrderRule> getOrderRuleList(String organizeCode, String workCenterCode, String checkType) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_TASK_TYPE.PREPARE_TASK.getValue(), MesPcnExtConstWords.TASK_TYPE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_ORDER_TYPE.EQU_CHECK.getValue(), MesPcnExtConstWords.ORDER_TYPE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.MES_OR_CREATE_RULE.TIME_TO_CREATE.getValue(), MesPcnExtConstWords.CREATE_RULE, packBean);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(checkType, MesPcnExtConstWords.CHECK_TYPE, packBean);
        return orderRuleRepository.findByHqlWhere(packBean);
    }

    private List<String> getCheckTypelist() {
        List<String> checkTypeList = new ArrayList<>();
        String dayCheck = MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.DAY_CHECK.getValue();
        String weekCheck = MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.WEEK_CHECK.getValue();
        String monthCheck = MesPcnExtEnumUtil.MES_EQUIPMENT_CHECK_TYPE.MONTH_CHECK.getValue();
        checkTypeList.add(weekCheck);
        checkTypeList.add(dayCheck);
        checkTypeList.add(monthCheck);
        return checkTypeList;
    }

    private List<MesEquipmentCheck> getEquipmentCheckList(String organizeCode, String checkType) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(checkType, MesPcnExtConstWords.CHECK_TYPE, packBean);
        return equipmentCheckRepository.findByHqlWhere(packBean);
    }

}
