package com.rongwei.bscommon.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rongwei.bscommon.sys.dao.*;
import com.rongwei.bscommon.sys.service.*;
import com.rongwei.bscommon.sys.utils.ApsUtils;
import com.rongwei.bsentity.domain.*;
import com.rongwei.bsentity.vo.*;
import com.rongwei.rwadmincommon.system.vo.SysUserVo;
import com.rongwei.rwcommon.base.BaseDo;
import com.rongwei.rwcommon.base.R;
import com.rongwei.rwcommon.utils.SecurityUtil;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.rwcommon.vo.MailDo;
import com.rongwei.rwcommonentity.commonservers.domain.SysMindMappingDo;

import com.rongwei.safecommon.fegin.CXCommonFeginClient;
import com.rongwei.safecommon.utils.CXCommonUtils;
import com.rongwei.safecommon.utils.SaveConstans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.rongwei.safecommon.utils.SaveConstans.DatePattern.DATE_PATTERN_YMD;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyContent.*;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyTitle.*;
import static com.rongwei.safecommon.utils.SaveConstans.NotifyType.*;

/**
 *
 */
@Service
public class ApsProductionOrderServiceImpl extends ServiceImpl<ApsProductionOrderDao, ApsProductionOrderDo>
        implements ApsProductionOrderService {
    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private ApsProcessOperationDao apsProcessOperationDao;
    @Autowired
    private ApsBlankOrderDao apsBlankOrderDao;
    @Autowired
    private ApsProductDetailDao apsProductDetailDao;
    @Autowired
    private ApsProcessOperationProcessEquDao apsProcessOperationProcessEquDao;
    @Autowired
    private ApsProcessOperationBackupDao apsProcessOperationBackupDao;
    @Autowired
    private ApsProcessOperationProcessEquBackupDao apsProcessOperationProcessEquBackupDao;
    @Autowired
    private ApsBlankOrderService apsBlankOrderService;
    @Autowired
    private ApsProcessOutputProductService apsProcessOutputProductService;
    @Autowired
    private CXCommonFeginClient autoCommonFeginClient;
    @Autowired
    private ApsProductDetailService apsProductDetailService;
    @Autowired
    private ApsProductionMergeOrderService apsProductionMergeOrderService;
    @Autowired
    private ApsOrderAlloyCompositionService apsOrderAlloyCompositionService;
    @Autowired
    private ApsProductionMergeOrderDao apsProductionMergeOrderDao;
    @Autowired
    private ApsProductionTechnicalRequirementDao apsProductionTechnicalRequirementDao;
    @Autowired
    private ApsOrderAlloyCompositionDao apsOrderAlloyCompositionDao;
    @Autowired
    private ApsProductionMergeOrderHistoryService apsProductionMergeOrderHistoryService;
    @Autowired
    private ApsProductDetailHistoryService apsProductDetailHistoryService;
    @Autowired
    private ApsOrderAlloyCompositionHistoryService apsOrderAlloyCompositionHistoryService;
    @Autowired
    private ApsProductionTechnicalRequirementHistoryService apsProductionTechnicalRequirementHistoryService;
    @Autowired
    private ApsBlankOrderHistoryService apsBlankOrderHistoryService;
    @Autowired
    private ApsProcessOutputProductDao apsProcessOutputProductDao;
    @Autowired
    private ApsProcessOutputProductHistoryService apsProcessOutputProductHistoryService;
    @Autowired
    private ApsProcessOperationHistoryService apsProcessOperationHistoryService;
    @Autowired
    private ApsProcessOperationOutMaterHistoryService apsProcessOperationOutMaterHistoryService;
    @Autowired
    private ApsProcessOperationEquHistoryService apsProcessOperationEquHistoryService;
    @Autowired
    private ApsProcessOperationOutMaterDao apsProcessOperationOutMaterDao;
    @Autowired
    private ApsProcessOperationEquDao apsProcessOperationEquDao;
    @Autowired
    private ApsProductionOrderHistoryService apsProductionOrderHistoryService;
    @Autowired
    private NewSysMindMappingService newSysMindMappingService;
    @Autowired
    private NewSysMindMappingDao newSysMindMappingDao;


    public static final String ERROR_MSG = "%s上诉订单的排程交货期大于承诺交货期";

    /**
     * 发布订单排程
     *
     * @param productionOrderIds
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R publish(List<String> productionOrderIds) {
        if (productionOrderIds.isEmpty()) {
            return R.ok();
        }
        // 如果 订单排程交货期>承诺交货期 抛出异常信息
        List<ApsProductionOrderDo> list = this.list(new LambdaQueryWrapper<ApsProductionOrderDo>()
                .in(ApsProductionOrderDo::getId, productionOrderIds)
                .apply(" SCHEDULEDELIVERYDATE>PROMISEDELIVERYDATE"));
        if (!list.isEmpty()) {
            String collect = list.stream()
                    .map(info -> info.getOrderno() + "-" + info.getCustomname())
                    .collect(Collectors.joining(";"));
            log.error("存在排程交货期大于承诺交货期 的订单：{}", collect);
            return R.error(String.format(ERROR_MSG, collect));
        }

        // 更新工序作业的生产状态和是否锁定=是
        apsProcessOperationDao.publish(productionOrderIds);

        apsProcessOperationProcessEquDao.publish(productionOrderIds);
        // 更新坯料计划的生产状态
        apsBlankOrderDao.publish(productionOrderIds);
        // 更新产品明细的生产状态
        apsProductDetailDao.publish(productionOrderIds);
        // 更新订单的生产状态
        this.baseMapper.publish(productionOrderIds);
        // 根据坯料ID 删除 备份数据
        List<ApsBlankOrderDo> apsBlankOrderDos = apsBlankOrderDao.selectList(new LambdaQueryWrapper<ApsBlankOrderDo>()
                .in(ApsBlankOrderDo::getProductionorderid, productionOrderIds));
        ApsUtils.clearBackup(null);
        return R.ok();
    }

    /**
     * 取消发布订单排程
     *
     * @param productionOrderIds
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R publishCancel(List<String> productionOrderIds) {
        // 更新工序作业的生产状态和是否锁定=是
        apsProcessOperationDao.publishCancel(productionOrderIds);
        apsProcessOperationProcessEquDao.publishCancel(productionOrderIds);
        // 更新坯料计划的生产状态
        apsBlankOrderDao.publishCancel(productionOrderIds);
        // 更新产品明细的生产状态
        apsProductDetailDao.publish(productionOrderIds);
        // 更新订单的生产状态
        this.baseMapper.publishCancel(productionOrderIds);
        List<ApsBlankOrderDo> apsBlankOrderDos = apsBlankOrderDao.selectList(new LambdaQueryWrapper<ApsBlankOrderDo>()
                .in(ApsBlankOrderDo::getProductionorderid, productionOrderIds));
        List<String> blankIds = apsBlankOrderDos.stream().map(ApsBlankOrderDo::getId).collect(Collectors.toList());
        // 根据坯料ID 删除 备份数据
        ApsUtils.clearBackup(null);
        return R.ok();
    }

    @Override
    @Transactional
    public R checkAndSaveOrUpdateOrder(CheckAndSaveOrUpdateOrderReq req) {
        //订单信息
        ApsProductionOrderDo apsProductionOrderDo = req.getApsProductionOrderDo();
        //合并订单信息
        List<ApsProductionMergeOrderDo> apsProductionMergeOrderDoList = req.getApsProductionMergeOrderDoList();
        //产品明细信息
        List<ApsProductDetailVo> apsProductDetailVoList = req.getApsProductDetailVoList();
        //坯料计划信息(坯料计划是一保存的状态，校验直接通过数据库查询)
        List<ApsBlankOrderDo> apsBlankOrderDoList = apsBlankOrderDao.selectList(new QueryWrapper<ApsBlankOrderDo>().lambda().eq(ApsBlankOrderDo::getProductionorderid, apsProductionOrderDo.getId()).orderByDesc(ApsBlankOrderDo::getModifydate));
        //是否需要检验坯料计划是否已排程
        Boolean checkSchedule = req.getCheckSchedule();
        //坯料计划校验等级
        Integer checkLevel = req.getCheckLevel();

        //=========检查坯料计划的个数和状态=============
        if (ObjectUtil.isEmpty(apsBlankOrderDoList)) {
            return R.error("坯料计划至少有一个");
        }
        if (checkLevel == 3) {
            for (int i = 0; i < apsBlankOrderDoList.size(); i++) {
                if (apsBlankOrderDoList.get(i).getIsstag().equals("是")) {
                    return R.error("第" + (i + 1) + "个坯料计划还未提交，请先提交坯料计划再提交订单");
                }
            }
        }

        //提交时需要校验是否已排程
        if (checkSchedule) {
            //如果坯料计划生产状态=待排程；错误提示：坯料计划 {输入物料描述} 还未排程
            for (ApsBlankOrderDo apsBlankOrderDo : apsBlankOrderDoList) {
                if (ObjectUtil.isNotEmpty(apsBlankOrderDo.getProductstatus()) && apsBlankOrderDo.getProductstatus().equals(SaveConstans.ProductionStatus.TO_BE_SCHEDULED)) {
                    return R.error("坯料计划 " + apsBlankOrderDo.getInputreportdescribe() + " 还未排程");
                }
            }
            //检查该订单所有作业明细，如果存在冲突，则错误提示：请先解决冲突再发布
            int count = this.baseMapper.selectConflictdesCount(apsProductionOrderDo.getId());
            if (count > 0) {
                return R.error("请先解决冲突再发布");
            }

//            //============校验承诺交期============
//            //如果承诺交货期为空，错误提示：请填写订单{订单号}{客户简称}的承诺交货期
//            if (ObjectUtil.isEmpty(apsProductionOrderDo.getPromisedeliverydate())) {
//                return R.error("请填写订单" + apsProductionOrderDo.getOrderno() + apsProductionOrderDo.getCustomname() + "的承诺交货期");
//            }
//            if (ObjectUtil.isEmpty(apsProductionOrderDo.getScheduledeliverydate())) {
//                return R.error("排程交货期不能为空");
//            }
//            //如果承诺交货期<排程交货期，错误提示：承诺交货期不能早于排程交货期{排程交货期}
//            if (apsProductionOrderDo.getPromisedeliverydate().compareTo(apsProductionOrderDo.getScheduledeliverydate()) < 0) {
//                return R.error("承诺交货期不能早于排程交货期" + DateUtil.format(apsProductionOrderDo.getScheduledeliverydate(), "yyyy-MM-dd"));
//            }
        }

        //============校验计划输出订单总重量==============
        //检查每个订单产品，如果该订单产品坯料计划输出总重量 不等于 该订单产品订单总数量；
        //错误提示：订单产品 {输入物料描述} 订单总数量与坯料计划输出总重量不一致
        if (ObjectUtil.isEmpty(apsProductDetailVoList) || apsProductDetailVoList.size() <= 0) {
            return R.error("产品明细至少有一个");
        }
//        for (ApsProductDetailVo apsProductDetailVo : apsProductDetailVoList) {
//            if (ObjectUtil.isEmpty(apsProductDetailVo.getTotalordercount()) || ObjectUtil.isEmpty(apsProductDetailVo.getPlanout()) || apsProductDetailVo.getTotalordercount().compareTo(apsProductDetailVo.getPlanout()) != 0) {
//                return R.error("订单产品 " + apsProductDetailVo.getInputmaterialdescription() + " 订单总数量与坯料计划输出总重量不一致");
//            }
//        }

        //查询此订单所有产品明细对应的输出成品的卷数和
//        List<ProductDetailIdAndPlanOutPutRollCountAllVo> planOutPutRollCountAllVos = this.baseMapper.getProductDetailIdAndPlanOutPutRollCountAll(apsProductDetailVoList.get(0).getMainid());
        //检查每个订单产品，如果该订单产品填写了卷数，
        //并且该订单产品对应坯料输出成品的计划输出订单卷数合计不等于订单产品的卷数，
        //错误提示：订单产品 {输入物料描述} 的卷数与坯料计划的计划输出订单卷数不一致
//        for (ApsProductDetailVo apsProductDetailVo : apsProductDetailVoList) {
//            if (ObjectUtil.isNotEmpty(apsProductDetailVo.getRollnum())) {
//                for (ProductDetailIdAndPlanOutPutRollCountAllVo planOutPutRollCountAllVo : planOutPutRollCountAllVos) {
//                    if (planOutPutRollCountAllVo.getProductDetailId().equals(apsProductDetailVo.getId())) {
//                        if (planOutPutRollCountAllVo.getPlanOutPutRollCountAll().equals(apsProductDetailVo.getRollnum())) {
//                            break;
//                        } else {
//                            return R.error("订单产品 " + apsProductDetailVo.getInputmaterialdescription() + " 的卷数与坯料计划的计划输出订单卷数不一致");
//                        }
//                    }
//                }
//            }
//        }

        //===============校验产品明细的长===================
        if (ObjectUtil.isEmpty(apsProductDetailVoList)) {
            return R.error("产品明细至少有一个");
        }

//        //获取产品明细的所有产品类型ID（去重）
//        Set<String> productTypeIds = apsProductDetailVoList.stream().map(ApsProductDetailVo::getProducttypeid).collect(Collectors.toSet());
//        String join = String.join("','", productTypeIds);
//
//        List<ProductTypeIdAndPidVo> productTypeIdAndPidList = this.baseMapper.selectProductTypeIdAndPid(join);
//        if (ObjectUtil.isNotEmpty(productTypeIdAndPidList)) {
//            for (ProductTypeIdAndPidVo productTypeIdAndPidVo : productTypeIdAndPidList) {
//                for (int i = 0; i < apsProductDetailVoList.size(); i++) {
//                    ApsProductDetailVo apsProductDetailVo = apsProductDetailVoList.get(i);
//                    if (apsProductDetailVo.getProducttypeid().equals(productTypeIdAndPidVo.getId())) {
//                        //如果是铝板或铝锭
//                        if (productTypeIdAndPidVo.getPid().equals(SaveConstans.ProductionType.LVBAN_ID) || productTypeIdAndPidVo.getPid().equals(SaveConstans.ProductionType.BANDING_ID)) {
//                            //判断长度是否为空
//                            if (ObjectUtil.isEmpty(apsProductDetailVo.getProlength())) {
//                                return R.error("第" + (i + 1) + "个产品明细，产品类型是铝板或板锭时长度必填");
//                            }
//                        }
//                    }
//                }
//            }
//        }

        List<ApsProductDetailDo> productDetailDoList = BeanUtil.copyToList(apsProductDetailVoList, ApsProductDetailDo.class);
        //================循环校验坯料计划===============
        for (int i = 0; i < apsBlankOrderDoList.size(); i++) {
            CheckAndSaveOrUpdateBlankReq checkAndSaveOrUpdateBlankReq = new CheckAndSaveOrUpdateBlankReq();
            checkAndSaveOrUpdateBlankReq.setApsBlankOrderDo(apsBlankOrderDoList.get(i));
            checkAndSaveOrUpdateBlankReq.setApsProcessOutputProductDoList(apsProcessOutputProductService.list(new QueryWrapper<ApsProcessOutputProductDo>().lambda().eq(ApsProcessOutputProductDo::getBlankid, apsBlankOrderDoList.get(i).getId())));
            checkAndSaveOrUpdateBlankReq.setApsProductDetailDoList(productDetailDoList);
            checkAndSaveOrUpdateBlankReq.setCheckLevel(checkLevel);
            if (checkSchedule) {
                checkAndSaveOrUpdateBlankReq.setCheckDevice(true);
            }

            R r = apsBlankOrderService.checkBlankOrder(checkAndSaveOrUpdateBlankReq, i + 1);
            if (!r.getCode().equals("200")) {
                return R.error(r.getMsg());
            }
        }

        //================校验通过，保存或更新订单相关信息=====================
        if (req.getIsNeedSave()) {
            //获取当前用户的所属工厂
            SysUserVo currentUser = CXCommonUtils.getCurrentUser();
            String tenantId = currentUser.getOrganizationDoList().get(0).getFullpid().split(",")[1];

            //保存主表信息
            apsProductionOrderDo.setTenantid(tenantId);
            this.saveOrUpdate(apsProductionOrderDo);

            //保存产品明细子表
            for (ApsProductDetailVo apsProductDetailVo : apsProductDetailVoList) {
                apsProductDetailVo.setTenantid(tenantId);
            }
            apsProductDetailService.saveOrUpdateBatch(productDetailDoList);

            //保存合并订单子表
            if (ObjectUtil.isNotEmpty(apsProductionMergeOrderDoList) && apsProductionMergeOrderDoList.size() > 0) {
                for (ApsProductionMergeOrderDo apsProductionMergeOrderDo : apsProductionMergeOrderDoList) {
                    apsProductionMergeOrderDo.setTenantid(tenantId);
                }
                apsProductionMergeOrderService.saveOrUpdateBatch(apsProductionMergeOrderDoList);
            }
        }

        if (req.getIsNeedPublish()) {
            //=============发布排程================
            List<String> blankIds = apsBlankOrderDoList.stream().map(ApsBlankOrderDo::getId).collect(Collectors.toList());
            R publish = apsBlankOrderService.publish(blankIds);
            if (!publish.getCode().equals("200")) {
                throw new RuntimeException(publish.getMsg());
            }
        }


        return R.ok();
    }

    /*
    订单未及时评审提醒
     */
    @Override
    public void orderOuttimeAudit() {
        log.info("订单未及时评审提醒开始");
        List<ApsProductionOrderDo> apsProductionOrderDos = this.baseMapper.getOrderOuttimeAudit();
        for (ApsProductionOrderDo apsProductionOrderDo : apsProductionOrderDos) {
            //系统通知（移动端和PC端个人工作台）
            CXCommonUtils.sendNotify(ORDEROUTTIMEAUDIT_TITLE, String.format(ORDEROUTTIME_AUDIT_CONTENT, apsProductionOrderDo.getOrderno()), null, Arrays.asList(apsProductionOrderDo.getCreateuserid().split(",")), apsProductionOrderDo.getId(), ORDEROUTTIME_AUDIT, false);

            //邮件提醒
            if (StringUtils.isNotEmpty(apsProductionOrderDo.getModifyusername())) {
                MailDo mailDo = new MailDo();
                mailDo.setReceiveEmail(apsProductionOrderDo.getModifyusername().split(","));
                mailDo.setNeedTransReceive(false);
                mailDo.setCcEmail(new String[]{});
                mailDo.setSubject(ORDEROUTTIMEAUDIT_TITLE);
                mailDo.setContent(String.format(ORDEROUTTIME_AUDIT_CONTENT, apsProductionOrderDo.getOrderno()));
                autoCommonFeginClient.sendHtmlMail(mailDo);
            }
        }
    }

    /*
    辅料申购提醒
     */
    @Override
    public void auxiliaryMaterial() {
        log.info("辅料申购提醒开始");
        List<ApsProductionOrderDo> apsProductionOrderDos = this.baseMapper.getAuxiliaryMaterial();
        for (ApsProductionOrderDo apsProductionOrderDo : apsProductionOrderDos) {
            //系统通知（移动端和PC端个人工作台）
            CXCommonUtils.sendNotify(AUXILIARYMATERIAL_TITLE, String.format(AUXILIARYMATERIAL_CONTENT, apsProductionOrderDo.getOrderno()), null, Arrays.asList(apsProductionOrderDo.getCreateuserid().split(",")), apsProductionOrderDo.getId(), AUXILIARYMATERIAL_REMIND, false);

            //邮件提醒
            if (StringUtils.isNotEmpty(apsProductionOrderDo.getModifyusername())) {
                MailDo mailDo = new MailDo();
                mailDo.setReceiveEmail(apsProductionOrderDo.getModifyusername().split(","));
                mailDo.setNeedTransReceive(false);
                mailDo.setCcEmail(new String[]{});
                mailDo.setSubject(AUXILIARYMATERIAL_TITLE);
                mailDo.setContent(String.format(AUXILIARYMATERIAL_CONTENT, apsProductionOrderDo.getOrderno()));
                autoCommonFeginClient.sendHtmlMail(mailDo);
            }
        }
    }

    @Override
    @Transactional
    @Deprecated
    public R changeOrder(ApsProductionOrderDo req) {
        if (ObjectUtil.isEmpty(req.getId())) {
            return R.error("订单Id不能为空");
        }
        //订单评审状态=待计划评审，订单调整日期=今天，
        this.baseMapper.changeOrderById(req.getId());

        //撤回发布订单所有坯料计划的排程结果，参见【订单排程/一键自动排程/撤回发布排程结果】
        List<String> orderIdList = new LinkedList<>();
        orderIdList.add(req.getId());
        R r = this.publishCancel(orderIdList);
        if (!r.getCode().equals("200")) {
            return R.error(r.getMsg());
        }

        return R.ok();
    }

    @Override
    @Transactional
    public R deleteOrder(DeleteOrderVo req) {
        if (ObjectUtil.isEmpty(req.getOrderId())) {
            return R.error("订单ID不能为空");
        }

        List<ApsBlankOrderDo> blankList = apsBlankOrderService.list(new QueryWrapper<ApsBlankOrderDo>().lambda().eq(ApsBlankOrderDo::getProductionorderid, req.getOrderId()));
        //清除排程备份
        if (req.getNeedDelBackup()) {
            //查询订单下的坯料计划

            List<String> blankIdList = blankList.stream().map(ApsBlankOrderDo::getId).collect(Collectors.toList());
            SysUserVo currentUser = CXCommonUtils.getCurrentUser();
            String factoryId = CXCommonUtils.getCurrentUserFactoryId(currentUser);
            apsProcessOperationBackupDao.deletedByBlankId(blankIdList, factoryId);
            apsProcessOperationProcessEquBackupDao.deletedByBlankId(blankIdList, factoryId);
        }

        //删除该订单，包括订单明细，合并订单及明细，坯料计划，工序作业
        //删除订单
        this.removeById(req.getOrderId());

        //删除订单明细子表
        apsProductDetailService.remove(new QueryWrapper<ApsProductDetailDo>().lambda().eq(ApsProductDetailDo::getMainid, req.getOrderId()));

        //删除合并订单子表
        apsProductionMergeOrderService.remove(new QueryWrapper<ApsProductionMergeOrderDo>().lambda().eq(ApsProductionMergeOrderDo::getMainid, req.getOrderId()));

        //删除合计成分要求子表
        apsOrderAlloyCompositionService.remove(new QueryWrapper<ApsOrderAlloyCompositionDo>().lambda().eq(ApsOrderAlloyCompositionDo::getProductionorderid, req.getOrderId()));

        //遍历删除坯料计划子表
        for (ApsBlankOrderDo apsBlankOrderDo : blankList) {
            apsBlankOrderService.removeBlankOrderAndChild(apsBlankOrderDo);
        }

        return R.ok();
    }

    /*
    作业延期提醒
     */
    @Override
    public void processDelay() {
        log.info("作业延期提醒开始");
        List<ApsProductionOrderDo> apsProductionOrderDos = this.baseMapper.getProcessDelay();
        for (ApsProductionOrderDo apsProductionOrderDo : apsProductionOrderDos) {
            //系统通知（移动端和PC端个人工作台）
            CXCommonUtils.sendNotify(PROCESSDELAY_TITLE, String.format(PROCESSDELAY_CONTENT, apsProductionOrderDo.getOrderno()), null, Arrays.asList(apsProductionOrderDo.getCreateuserid().split(",")), apsProductionOrderDo.getId(), PROCESSDELAY_REMIND, false);

            //邮件提醒
            if (StringUtils.isNotEmpty(apsProductionOrderDo.getModifyusername())) {
                MailDo mailDo = new MailDo();
                mailDo.setReceiveEmail(apsProductionOrderDo.getModifyusername().split(","));
                mailDo.setNeedTransReceive(false);
                mailDo.setCcEmail(new String[]{});
                mailDo.setSubject(PROCESSDELAY_TITLE);
                mailDo.setContent(String.format(PROCESSDELAY_CONTENT, apsProductionOrderDo.getOrderno()));
                autoCommonFeginClient.sendHtmlMail(mailDo);
            }
        }
    }

    /*
    报工不合格提醒
     */
    @Override
    public void reportUnqualify() {
        log.info("报工不合格提醒开始");
        List<ApsProductionOrderDo> apsProductionOrderDos = this.baseMapper.getReportUnqualify();
        if (apsProductionOrderDos.isEmpty()) {
            return;
        }
        //所有的坯料计划id
        List<String> blankIds = apsProductionOrderDos.stream().map(ApsProductionOrderDo::getAuditorid).distinct().collect(Collectors.toList());
        //坯料输出成品
        List<ApsProcessOutputProductDo> apsProcessOutputProductDos = apsProcessOutputProductService.list(new LambdaQueryWrapper<ApsProcessOutputProductDo>()
                .in(ApsProcessOutputProductDo::getBlankid, blankIds)
                .eq(BaseDo::getDeleted, "0")
                .orderByDesc(ApsProcessOutputProductDo::getModifydate));

        //按照订单分组
        Map<String, List<ApsProductionOrderDo>> orderList = apsProductionOrderDos.stream().collect(Collectors.groupingBy(e -> e.getId()));
        final String[] content = {""};
        orderList.forEach((k, olist) -> {
            //系统通知（移动端和PC端个人工作台）
            CXCommonUtils.sendNotify(REPORTUNQUALIFY_TITLE, REPORTUNQUALIFY_CONTENT, null, Arrays.asList(olist.get(0).getCreateuserid().split(",")), k, REPORTUNQUALIFY_REMIND, false);

            //邮件内容
            content[0] = "<div>报工检验不合格，请及时调整计划</div>" +
                    "<div>客户【" + olist.get(0).getCustomname() + "】【" + DateUtil.format(olist.get(0).getOrderdate(), DATE_PATTERN_YMD) + "】的订单【" + olist.get(0).getOrderno() + "】</div>";
            //按照坯料计划分组
            Map<String, List<ApsProductionOrderDo>> blankList = olist.stream().collect(Collectors.groupingBy(o -> o.getAuditorid()));
            blankList.forEach((b, blist) -> {
                List<ApsProcessOutputProductDo> apsProcessOutputProductDoList = apsProcessOutputProductDos.stream().filter(out -> out.getBlankid().equals(b)).collect(Collectors.toList());
                for (ApsProcessOutputProductDo apsProcessOutputProductDo : apsProcessOutputProductDoList) {
                    content[0] += "<div>产品【" + apsProcessOutputProductDo.getProductname() + "】</div>";
                }
            });

            for (ApsProductionOrderDo apsProductionOrderDo : olist) {
                content[0] += "<div>批次号【" + apsProductionOrderDo.getAuditor() + "】工序【" + apsProductionOrderDo.getCustomorderno() + "】检验等级【" + apsProductionOrderDo.getCustomordertype() + "】</div>";
                content[0] += "<div>主要缺陷【" + (apsProductionOrderDo.getRemark() == null ? "" : apsProductionOrderDo.getRemark()) + "】</div>";
                content[0] += "<div>次要缺陷【" + (apsProductionOrderDo.getOtherprecaution() == null ? "" : apsProductionOrderDo.getOtherprecaution()) + "】</div>";
            }

            //邮件提醒
            if (StringUtils.isNotEmpty(olist.get(0).getModifyusername())) {
                MailDo mailDo = new MailDo();
                mailDo.setReceiveEmail(olist.get(0).getModifyusername().split(","));
                mailDo.setNeedTransReceive(false);
                mailDo.setCcEmail(new String[]{});
                mailDo.setSubject(REPORTUNQUALIFY_TITLE);
                mailDo.setContent(content[0]);
                autoCommonFeginClient.sendHtmlMail(mailDo);
            }
        });
    }

    /*
    根据保存前数据的 id 获取撤回前版本所有主子表信息
     */
    @Override
    public R saveHistoryInfo(String id) {
        //获取保存前主子表信息
        ApsProductionOrderDo apsProductionOrderDo = this.baseMapper.selectDataInfo(id);
        if (apsProductionOrderDo != null) {
            //创建一个map集合
            Map<String, String> ApsProductDetailMap = new HashMap<>();

            ApsProductionOrderHistoryDo apsProductionOrderHistoryDo = new ApsProductionOrderHistoryDo();
            BeanUtils.copyProperties(apsProductionOrderDo, apsProductionOrderHistoryDo);
            apsProductionOrderHistoryDo.setHistorytableid(apsProductionOrderDo.getId());
            apsProductionOrderHistoryDo.setId(SecurityUtil.getUUID());
            apsProductionOrderHistoryService.save(apsProductionOrderHistoryDo);

            //获取合并订单列表
            List<ApsProductionMergeOrderDo> apsProductionMergeOrderDoList = apsProductionMergeOrderDao.selectApsProductionMergeOrderDoByMainId(apsProductionOrderDo.getId());
            if (apsProductionMergeOrderDoList != null && apsProductionMergeOrderDoList.size() > 0) {
                for (ApsProductionMergeOrderDo apsProductionMergeOrderDo : apsProductionMergeOrderDoList) {
                    //将apsProductionMergeOrderDo的数据复制到apsProductionMergeOrderHistoryDo
                    ApsProductionMergeOrderHistoryDo apsProductionMergeOrderHistoryDo = new ApsProductionMergeOrderHistoryDo();
                    BeanUtils.copyProperties(apsProductionMergeOrderDo, apsProductionMergeOrderHistoryDo);
                    //订单表和历史版本表关联
                    apsProductionMergeOrderHistoryDo.setMainid(apsProductionOrderHistoryDo.getId());
                    apsProductionMergeOrderHistoryDo.setId(SecurityUtil.getUUID());
                    //保存apsProductionMergeOrderHistoryDo
                    apsProductionMergeOrderHistoryService.save(apsProductionMergeOrderHistoryDo);
                }

            }


            //获取产品明细
            List<ApsProductDetailDo> apsProductDetailDoList = apsProductDetailDao.getProductDetailByMainId(apsProductionOrderDo.getId());
            if (apsProductDetailDoList != null && apsProductDetailDoList.size() > 0) {

                for (ApsProductDetailDo apsProductDetailDo : apsProductDetailDoList) {
                    //将apsProductDetailDo的数据复制到apsProductDetailHistoryDo
                    ApsProductDetailHistoryDo apsProductDetailHistoryDo = new ApsProductDetailHistoryDo();
                    BeanUtils.copyProperties(apsProductDetailDo, apsProductDetailHistoryDo);
                    //关联历史版本主表 id
                    apsProductDetailHistoryDo.setMainid(apsProductionOrderHistoryDo.getId());
                    apsProductDetailHistoryDo.setId(SecurityUtil.getUUID());

                    //保存aps
                    apsProductDetailHistoryService.save(apsProductDetailHistoryDo);

                    //通过产品明细 id  获取 坯料输出成品 aps_process_output_product （关联id：PRODUCTID）
                    List<ApsProcessOutputProductDo> apsProcessOutputProductDoList = apsProcessOutputProductDao.getProcessOutputProductByProductid(apsProductDetailDo.getId());
                    if (apsProcessOutputProductDoList != null && apsProcessOutputProductDoList.size() > 0) {

                        for (ApsProcessOutputProductDo apsProcessOutputProductDo : apsProcessOutputProductDoList) {
                            //向ApsProductDetailMap集合中插入产品明细数据的老 id 和历史版本对应数据的新 id
                            ApsProductDetailMap.put(apsProcessOutputProductDo.getId(), apsProductDetailHistoryDo.getId());
                        }
                    }
                }
            }
            //获取技术要求
            List<ApsProductionTechnicalRequirementDo> apsProductionTechnicalRequirementDoList = apsProductionTechnicalRequirementDao.selectByOrderid(apsProductionOrderDo.getId());
            if (apsProductionTechnicalRequirementDoList != null && apsProductionTechnicalRequirementDoList.size() > 0) {
                for (ApsProductionTechnicalRequirementDo apsProductionTechnicalRequirementDo : apsProductionTechnicalRequirementDoList) {
                    ApsProductionTechnicalRequirementHistoryDo apsProductionTechnicalRequirementHistoryDo = new ApsProductionTechnicalRequirementHistoryDo();
                    BeanUtils.copyProperties(apsProductionTechnicalRequirementDo, apsProductionTechnicalRequirementHistoryDo);
                    apsProductionTechnicalRequirementHistoryDo.setOrderid(apsProductionOrderHistoryDo.getId());
                    apsProductionTechnicalRequirementHistoryDo.setId(SecurityUtil.getUUID());
                    apsProductionTechnicalRequirementHistoryService.save(apsProductionTechnicalRequirementHistoryDo);
                }
            }
            //获取合金成分要求
            List<ApsOrderAlloyCompositionDo> apsOrderAlloyCompositionDoList = apsOrderAlloyCompositionDao.getAlloyCompositionByProductionorderId(apsProductionOrderDo.getId());

            if (apsOrderAlloyCompositionDoList != null && apsOrderAlloyCompositionDoList.size() > 0) {

                for (ApsOrderAlloyCompositionDo apsOrderAlloyCompositionDo : apsOrderAlloyCompositionDoList) {
                    ApsOrderAlloyCompositionHistoryDo apsOrderAlloyCompositionHistoryDo = new ApsOrderAlloyCompositionHistoryDo();
                    BeanUtils.copyProperties(apsOrderAlloyCompositionDo, apsOrderAlloyCompositionHistoryDo);
                    apsOrderAlloyCompositionHistoryDo.setProductionorderid(apsProductionOrderHistoryDo.getId());
                    apsOrderAlloyCompositionHistoryDo.setId(SecurityUtil.getUUID());
                    apsOrderAlloyCompositionHistoryService.save(apsOrderAlloyCompositionHistoryDo);
                }
            }
            //获取坯料计划
            List<ApsBlankOrderDo> apsBlankOrderDoList = apsBlankOrderDao.selectBlankOrderByProductionorderId(apsProductionOrderDo.getId());

            if (apsBlankOrderDoList != null && apsBlankOrderDoList.size() > 0) {

                for (ApsBlankOrderDo apsBlankOrderDo : apsBlankOrderDoList) {
                    ApsBlankOrderHistoryDo apsBlankOrderHistoryDo = new ApsBlankOrderHistoryDo();
                    BeanUtils.copyProperties(apsBlankOrderDo, apsBlankOrderHistoryDo);
                    apsBlankOrderHistoryDo.setProductionorderid(apsProductionOrderHistoryDo.getId());
                    apsBlankOrderHistoryDo.setId(SecurityUtil.getUUID());
                    apsBlankOrderHistoryService.save(apsBlankOrderHistoryDo);


                    //根据坯料计划id获取 坯料输出成品  aps_process_output_product子表数据
                    List<ApsProcessOutputProductDo> apsProcessOutputProductDoList = apsProcessOutputProductDao.getProcessOutputProductByBlankId(apsBlankOrderDo.getId());
                    if (apsProcessOutputProductDoList != null && apsProcessOutputProductDoList.size() > 0) {
                        for (ApsProcessOutputProductDo apsProcessOutputProductDo : apsProcessOutputProductDoList) {
                            ApsProcessOutputProductHistoryDo apsProcessOutputProductHistoryDo = new ApsProcessOutputProductHistoryDo();
                            BeanUtils.copyProperties(apsProcessOutputProductDo, apsProcessOutputProductHistoryDo);
                            //ApsProductDetailMap不为 null 则 如果键为apsProcessOutputProductDo.getId() 数据存在 map 中 则获取到其值 并且赋值到productid 字段
                            if (ApsProductDetailMap != null && ApsProductDetailMap.containsKey(apsProcessOutputProductDo.getId())) {
                                apsProcessOutputProductHistoryDo.setProductid(ApsProductDetailMap.get(apsProcessOutputProductDo.getId()));
                            }
                            apsProcessOutputProductHistoryDo.setBlankid(apsBlankOrderHistoryDo.getId());
                            apsProcessOutputProductHistoryDo.setId(SecurityUtil.getUUID());
                            apsProcessOutputProductHistoryService.save(apsProcessOutputProductHistoryDo);

                        }
                    }

                    //根据工序作业 id 获取工艺路线图数据 赋值历史表的坯料计划 id
                    List<NewSysMindMappingDo> sysMindMappingDoList = newSysMindMappingDao.getSysMindMappingByMainId(apsBlankOrderDo.getId());

                    if (sysMindMappingDoList != null && sysMindMappingDoList.size() > 0) {
                        for (NewSysMindMappingDo sysMindMappingDo : sysMindMappingDoList) {
                            NewSysMindMappingDo newSysMindMappingDo = new NewSysMindMappingDo();
                            BeanUtils.copyProperties(sysMindMappingDo, newSysMindMappingDo);
                            newSysMindMappingDo.setBsid(apsBlankOrderHistoryDo.getId());
                            newSysMindMappingDo.setId(SecurityUtil.getUUID());
                            newSysMindMappingService.save(newSysMindMappingDo);
                        }
                    }

                    //根据坯料计划id获取 工序作业  aps_process_operation 子表数据
                    List<ApsProcessOperationDo> apsProcessOperationDoList = apsProcessOperationDao.getProcessOperationByBlankId(apsBlankOrderDo.getId());

                    if (apsProcessOperationDoList != null && apsProcessOperationDoList.size() > 0) {
                        for (ApsProcessOperationDo apsProcessOperationDo : apsProcessOperationDoList) {
                            ApsProcessOperationHistoryDo apsProcessOperationHistoryDo = new ApsProcessOperationHistoryDo();
                            BeanUtils.copyProperties(apsProcessOperationDo, apsProcessOperationHistoryDo);
                            apsProcessOperationHistoryDo.setBlankid(apsBlankOrderHistoryDo.getId());
                            apsProcessOperationHistoryDo.setId(SecurityUtil.getUUID());
                            apsProcessOperationHistoryService.save(apsProcessOperationHistoryDo);

                            NewSysMindMappingDo newSysMindMappingDo = newSysMindMappingDao.getDataInfo(apsBlankOrderHistoryDo.getId(), apsProcessOperationHistoryDo.getCraftstepid(), apsProcessOperationHistoryDo.getLevel());
                            if (newSysMindMappingDo != null) {
                                //更改newSysMindMappingDo 中的 id 为apsProcessOperationHistoryDo.getId()
                                newSysMindMappingDao.updateDataInfo(newSysMindMappingDo.getId(), apsProcessOperationHistoryDo.getId());
                            }
                            //根据工序作业 id 获取 输出物料 aps_process_operation_out_mater
                            List<ApsProcessOperationOutMaterDo> apsProcessOperationOutMaterDoList = apsProcessOperationOutMaterDao.getProcessOperationOutMaterByMainId(apsProcessOperationDo.getId());
                            if (apsProcessOperationOutMaterDoList != null && apsProcessOperationOutMaterDoList.size() > 0) {
                                for (ApsProcessOperationOutMaterDo apsProcessOperationOutMaterDo : apsProcessOperationOutMaterDoList) {
                                    ApsProcessOperationOutMaterHistoryDo apsProcessOperationOutMaterHistoryDo = new ApsProcessOperationOutMaterHistoryDo();
                                    BeanUtils.copyProperties(apsProcessOperationOutMaterDo, apsProcessOperationOutMaterHistoryDo);
                                    apsProcessOperationOutMaterHistoryDo.setMainid(apsProcessOperationHistoryDo.getId());
                                    apsProcessOperationOutMaterHistoryDo.setId(SecurityUtil.getUUID());
                                    apsProcessOperationOutMaterHistoryService.save(apsProcessOperationOutMaterHistoryDo);
                                }
                            }
                            //根据工序作业 id 获取 可选设备 aps_process_operation_equ
                            List<ApsProcessOperationEquDo> apsProcessOperationEquDoList = apsProcessOperationEquDao.getProcessOperationEquByMainId(apsProcessOperationDo.getId());

                            if (apsProcessOperationEquDoList != null && apsProcessOperationEquDoList.size() > 0) {
                                for (ApsProcessOperationEquDo apsProcessOperationEquDo : apsProcessOperationEquDoList) {
                                    ApsProcessOperationEquHistoryDo apsProcessOperationEquHistoryDo = new ApsProcessOperationEquHistoryDo();
                                    BeanUtils.copyProperties(apsProcessOperationEquDo, apsProcessOperationEquHistoryDo);
                                    apsProcessOperationEquHistoryDo.setMainid(apsProcessOperationHistoryDo.getId());
                                    apsProcessOperationEquHistoryDo.setId(SecurityUtil.getUUID());
                                    apsProcessOperationEquHistoryService.save(apsProcessOperationEquHistoryDo);
                                }
                            }


                        }
                    }

                    //获取 以上新增的工艺路线图数据
                    List<NewSysMindMappingDo> newSysMindMappingDoList = newSysMindMappingDao.getSysMindMappingByMainId(apsBlankOrderHistoryDo.getId());
                    if (newSysMindMappingDoList != null && newSysMindMappingDoList.size() > 0) {
                        // 获取列表中level的最大值
                        int maxLevel = 0;
                        for (NewSysMindMappingDo mapping : newSysMindMappingDoList) {
                            if (mapping.getLevel() > maxLevel) {
                                maxLevel = mapping.getLevel();
                            }
                        }
                        // 遍历列表，根据不同的level设置parentid
                        for (NewSysMindMappingDo mapping : newSysMindMappingDoList) {
                            int currentLevel = mapping.getLevel();
                            if (currentLevel == 2) {
                                String parentId = getIdByLevel(newSysMindMappingDoList, 0);
                                mapping.setParentid(parentId);
                                newSysMindMappingService.updateById(mapping);
                            } else if (currentLevel == 3) {
                                String parentId = getIdByLevel(newSysMindMappingDoList, 2);
                                mapping.setParentid(parentId);
                                newSysMindMappingService.updateById(mapping);
                            } else if (currentLevel == 4) {
                                String parentId = getIdByLevel(newSysMindMappingDoList, 3);
                                mapping.setParentid(parentId);
                                newSysMindMappingService.updateById(mapping);
                            } else if (currentLevel > 4 && currentLevel <= maxLevel) {
                                String parentId = getIdByLevel(newSysMindMappingDoList, currentLevel - 1);
                                mapping.setParentid(parentId);
                                newSysMindMappingService.updateById(mapping);
                            }
                        }
                    }
                }
            }
        }
        return R.ok();
    }

    // 根据level获取对应的id
    private String getIdByLevel(List<NewSysMindMappingDo> mappingList, int level) {
        for (NewSysMindMappingDo mapping : mappingList) {
            if (mapping.getLevel() == level) {
                return mapping.getId();
            }
        }
        return null;
    }

}




