package com.ximai.mes.pro.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ximai.common.constant.UserConstants;
import com.ximai.common.utils.MessageUtils;
import com.ximai.common.utils.data.DataUtil;
import com.ximai.common.utils.data.ExceptionUtil;
import com.ximai.mes.md.domain.MdItem;
import com.ximai.mes.md.mapper.MdItemMapper;
import com.ximai.mes.pro.domain.ProRecoilMaterial;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkOrderProcessItem;
import com.ximai.mes.pro.domain.task.ProTask;
import com.ximai.mes.pro.mapper.ProRecoilMaterialMapper;
import com.ximai.mes.pro.mapper.proWorkOrder.ProWorkOrderProcessItemMapper;
import com.ximai.mes.pro.service.IProRecoilMaterialService;
import com.ximai.mes.util.PackQrInfo;
import com.ximai.system.strategy.AutoCodeUtil;
import org.aspectj.bridge.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 反冲料登记Service业务层处理
 *
 * @author generator
 * @date 2024-02-22
 */
@Service
public class ProRecoilMaterialServiceImpl implements IProRecoilMaterialService {
    @Autowired
    private AutoCodeUtil autoCodeUtil;

    @Autowired
    private ProRecoilMaterialMapper proRecoilMaterialMapper;
    @Resource
    private ProWorkOrderProcessItemMapper proWorkOrderProcessItemMapper;
    @Resource
    private MdItemMapper mdItemMapper;

    @Override
    public void scan(String code, Long taskId) {
        PackQrInfo packQrInfo = new PackQrInfo();
        String sapItemCode = packQrInfo.getMatnr();
        QueryWrapper<ProWorkOrderProcessItem> qw = new QueryWrapper<>();
        qw.eq("t1.task_id", taskId);
        qw.eq("is_backflush", "Y");
        List<ProWorkOrderProcessItem> processItems = proWorkOrderProcessItemMapper.selectProcessItemByQw(qw);
        Optional<ProWorkOrderProcessItem> any = processItems.stream().filter(x -> Objects.equals(x.getSapItemCode(), sapItemCode)).findAny();
        ExceptionUtil.checkTrueThrowException(!any.isPresent(), MessageUtils.message("pro.material.error.not.exist"));


        List<MdItem> list = mdItemMapper.selectListByQw(new QueryWrapper<MdItem>().eq("sap_item_code", sapItemCode));
        ExceptionUtil.checkTrueThrowException(CollectionUtil.isEmpty(list) || list.get(0) == null, MessageUtils.message("pro.material.error.not.exist"));
        MdItem mdItem = list.get(0);

        ProRecoilMaterial proRecoilMaterial = new ProRecoilMaterial();
        proRecoilMaterial.setBatchNo(packQrInfo.getBatchNo());
        proRecoilMaterial.setPackNo(packQrInfo.getPackNo());
        proRecoilMaterial.setTaskId(taskId);
        proRecoilMaterial.setQuantity(packQrInfo.getPacmg().intValue());
        proRecoilMaterial.setItemId(mdItem.getItemId());
        proRecoilMaterial.setItemName(mdItem.getItemName());
        proRecoilMaterial.setSapItemCode(mdItem.getSapItemCode());
        proRecoilMaterial.setStatus(0);
        this.insertProRecoilMaterial(proRecoilMaterial);
    }

    // 检查倒冲料是否满足
    @Override
    public boolean checkRecoilMaterial(ProTask proTask) {
        List<ProRecoilMaterial> recoilMaterialList = getRecoilMaterialList(proTask.getTaskId());
        if (CollectionUtil.isNotEmpty(recoilMaterialList)) {
            for (ProRecoilMaterial proRecoilMaterial : recoilMaterialList) {
                ExceptionUtil.checkTrueThrowException(proRecoilMaterial.getRequestSum() > proRecoilMaterial.getSum(), MessageUtils.message("pro.request.material.error4"));
            }
            return true;
        } else {
            return false;
        }

    }

    @Override
    public boolean checkRecoilMaterialIsExist(Long taskWorkunitId) {
        QueryWrapper<ProWorkOrderProcessItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ptw.task_workunit_id", taskWorkunitId);
        queryWrapper.eq("is_backflush", "Y");
        return CollectionUtil.isNotEmpty(proWorkOrderProcessItemMapper.selectProcessItemByQw(queryWrapper));
    }

    @Override
    public List<ProRecoilMaterial> getRecoilMaterialList(Long taskId) {
        QueryWrapper<ProWorkOrderProcessItem> qw = new QueryWrapper<>();
        qw.eq("t1.task_id", taskId);
        qw.eq("is_backflush", "Y");
        List<ProWorkOrderProcessItem> processItems = proWorkOrderProcessItemMapper.selectProcessItemByQw(qw);
        if (CollectionUtil.isEmpty(processItems)) {
            return new ArrayList<>();
        }

        List<String> sapItemCodes = processItems.stream().map(ProWorkOrderProcessItem::getSapItemCode).collect(Collectors.toList());
        Map<String, List<ProRecoilMaterial>> rmMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(sapItemCodes)) {
            QueryWrapper<ProRecoilMaterial> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("t1.task_id", taskId);
            queryWrapper.in("t1.sap_item_code", sapItemCodes);
            queryWrapper.notIn("t1.status", 1);
            List<ProRecoilMaterial> list = proRecoilMaterialMapper.selectListByQw(queryWrapper);
            rmMap = list.stream().collect(Collectors.groupingBy(x -> x.getSapItemCode() + "##" + x.getItemName()));
        }


        Map<String, DoubleSummaryStatistics> processItemMap = processItems.stream().collect(Collectors.groupingBy(x -> x.getSapItemCode() + "##" + x.getItemName(), Collectors.summarizingDouble(x -> DataUtil.getNormalData(x.getQuantity()).doubleValue())));

        List<ProRecoilMaterial> objects = new ArrayList<>();
        for (Map.Entry<String, DoubleSummaryStatistics> entry : processItemMap.entrySet()) {
            String key = entry.getKey();
            DoubleSummaryStatistics value = entry.getValue();
            String[] split = key.split("##");
            String sapItemCode = split[0];
            String itemName = split[1];
            ProRecoilMaterial material = new ProRecoilMaterial();
            material.setSapItemCode(sapItemCode);
            material.setItemName(itemName);
            material.setRequestSum(value.getSum());

            if (CollectionUtil.isNotEmpty(rmMap)) {
                List<ProRecoilMaterial> proRecoilMaterials = rmMap.get(key);
                Map<String, IntSummaryStatistics> batchSum = proRecoilMaterials.stream().collect(Collectors.groupingBy(x -> x.getBatchNo() + x.getPackNo(), Collectors.summarizingInt(x -> DataUtil.getNormalData(x.getQuantity()))));

                IntSummaryStatistics statistics = rmMap.values().stream().collect(Collectors.summarizingInt(x -> x.stream().map(y -> DataUtil.getNormalData(y.getQuantity())).reduce(0, Integer::sum)));

                if (batchSum.size() == 1) {
                    List<String> batchNos = new ArrayList<>(batchSum.keySet());
                    material.setBatchNo(batchNos.get(0));
                }
                material.setProRecoilMaterialList(proRecoilMaterials);
                material.setSum(DataUtil.getNormalData(statistics.getSum()));
            } else {
                material.setSum(0L);
            }
            objects.add(material);
        }

        return objects;
    }

    /**
     * 查询反冲料登记
     *
     * @param recoilMaterialId 反冲料登记主键
     * @return 反冲料登记
     */
    @Override
    public ProRecoilMaterial selectProRecoilMaterialById(Long recoilMaterialId) {
        return proRecoilMaterialMapper.selectProRecoilMaterialById(recoilMaterialId);
    }

    /**
     * 查询反冲料登记列表
     *
     * @param proRecoilMaterial 反冲料登记
     * @return 反冲料登记
     */
    @Override
    public List<ProRecoilMaterial> selectProRecoilMaterialList(ProRecoilMaterial proRecoilMaterial) {
        return proRecoilMaterialMapper.selectProRecoilMaterialList(proRecoilMaterial);
    }

    /**
     * 新增反冲料登记
     *
     * @param proRecoilMaterial 反冲料登记
     * @return 结果
     */
    @Override
    public int insertProRecoilMaterial(ProRecoilMaterial proRecoilMaterial) {
        if (proRecoilMaterial.getRecoilMaterialCode() == null) {
            proRecoilMaterial.setRecoilMaterialCode(autoCodeUtil.genSerialCode(UserConstants.RECOIL_MATERIAL_CODE, ""));
        }
        proRecoilMaterial.createAction();
        return proRecoilMaterialMapper.insertProRecoilMaterial(proRecoilMaterial);
    }

    /**
     * 修改反冲料登记
     *
     * @param proRecoilMaterial 反冲料登记
     * @return 结果
     */
    @Override
    public int updateProRecoilMaterial(ProRecoilMaterial proRecoilMaterial) {
        proRecoilMaterial.updateAction();
        return proRecoilMaterialMapper.updateProRecoilMaterial(proRecoilMaterial);
    }

    /**
     * 批量删除反冲料登记
     *
     * @param recoilMaterialIds 需要删除的反冲料登记主键
     * @return 结果
     */
    @Override
    public int deleteProRecoilMaterialByIds(Long[] recoilMaterialIds) {
        return proRecoilMaterialMapper.deleteProRecoilMaterialByIds(recoilMaterialIds);
    }

    /**
     * 删除反冲料登记信息
     *
     * @param id 反冲料登记主键
     * @return 结果
     */
    @Override
    public int deleteProRecoilMaterialById(Long id) {
        return proRecoilMaterialMapper.deleteProRecoilMaterialById(id);
    }
}
