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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesCutRawErrorProofingService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.MesPcnException;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesCutRawErrorProofingModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesCutUpdateRawLengthModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.bean.ListPager;
import cn.estsh.i3plus.pojo.base.common.Pager;
import cn.estsh.i3plus.pojo.base.common.PagerHelper;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.*;
import cn.estsh.i3plus.pojo.mes.repository.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @PROJECT_NAME: i3plus-mes-yfai
 * @DESCRIPTION:
 * @USER: xinwang.yi
 * @DATE: 2024-09-04 9:54
 */
@Service
public class MesCutRawErrorProofingService implements IMesCutRawErrorProofingService {

    public static final int CUR_SCAN_TYPE_BY_ORDER_SN = 1;
    public static final int CUR_SCAN_TYPE_BY_RAW_SN = 2;

    @Autowired
    private MesWorkOrderCutRepository workOrderCutRepository;

    @Autowired
    private MesWorkOrderCutMaterialRepository workOrderCutMaterialRepository;

    @Autowired
    private MesMaterialSnRepository materialSnRepository;

    @Autowired
    private MesCutModifyRawLengthRecordRepository cutModifyRawLengthRecordRepository;

    @Autowired
    private MesCutSchemeRepository cutSchemeRepository;

    @Override
    public MesCutRawErrorProofingModel doScanSn(MesCutRawErrorProofingModel model) {

        MesCutRawErrorProofingModel result = new MesCutRawErrorProofingModel();
        result.setCutWorkOrderNo(model.getCutWorkOrderNo());
            // 为 1 则为裁片工单码
        if (model.getCurScanType() == null || model.getCurScanType() == CUR_SCAN_TYPE_BY_ORDER_SN) {

            MesWorkOrderCut workOrderCutDb = getMesWorkOrderCut(model);

            if (workOrderCutDb == null) MesPcnException.throwMesBusiException("裁片工单【%s】不存在", model.getSn());

            DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack(workOrderCutDb.getCutCode(), MesPcnExtConstWords.CUT_CODE, packBean);
            MesCutScheme cutScheme = cutSchemeRepository.getByProperty(packBean);

            if (cutScheme == null) MesPcnException.throwMesBusiException("裁片工单【%s】所属裁片方案无效", model.getSn());

            if (workOrderCutDb.getWorkOrderStatus() == MesExtEnumUtil.CUT_ORDER_STATUS.RELEASED.getValue() && cutScheme.getIsCheckMaterial() == CommonEnumUtil.FALSE) MesPcnException.throwMesBusiException("裁片工单【%s】无需校验原材料", model.getSn());

            if (workOrderCutDb.getWorkOrderStatus() != MesExtEnumUtil.CUT_ORDER_STATUS.RELEASED.getValue()) MesPcnException.throwMesBusiException("裁片工单【%s】状态不为【%s】", model.getSn(), MesExtEnumUtil.CUT_ORDER_STATUS.RELEASED.getDescription());

            result.setCurScanType(CUR_SCAN_TYPE_BY_RAW_SN);
            result.setCutWorkOrderNo(workOrderCutDb.getCutWorkOrderNo());
            result.setIsRedirect(CommonEnumUtil.FALSE);
            result.setIsReset(CommonEnumUtil.FALSE);

        } else {
            result.setCurScanType(CUR_SCAN_TYPE_BY_RAW_SN);
            // 校验条码有效性

            String[] valueArray = model.getSn().split("\\|");

            int valueLength = valueArray.length;

            if (valueLength < 5) MesPcnException.throwMesBusiException("条码【%s】长度少于5", model.getSn());
            if (valueLength > 9) MesPcnException.throwMesBusiException("条码【%s】长度超出9", model.getSn());

            List<MesWorkOrderCutMaterial> workOrderCutMaterialList = getWorkOrderCutMaterialList(model);

            Map<String, MesWorkOrderCutMaterial> workOrderCutMaterialMap = workOrderCutMaterialList.stream()
                    .collect(Collectors.toMap(MesWorkOrderCutMaterial::getPartNo, Function.identity(), (x, y) -> y));

            // 物料编码
            String partNo = valueArray[3];
            // 原材料长度
            String lengthStr = valueArray[4];

            Double length = 0.0;

            if (!workOrderCutMaterialMap.containsKey(partNo)) MesPcnException.throwMesBusiException("扫描条码【%s】零件号【%s】不在裁片方案原材料中", model.getSn(), partNo);

            // 为 2 则为条码
            DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
            DdlPreparedPack.getStringEqualPack(model.getSn(), MesPcnExtConstWords.SN, packBean);
            MesMaterialSn materialSnDb = materialSnRepository.getByProperty(packBean);

            MesWorkOrderCutMaterial workOrderCutMaterial = workOrderCutMaterialMap.get(partNo);

            if (materialSnDb != null) {
                if (materialSnDb.getSurplusLength() == 0) MesPcnException.throwMesBusiException("条码【%s】已无剩余长度", model.getSn());
                length = materialSnDb.getSurplusLength();
                ConvertBean.serviceModelUpdate(materialSnDb, model.getUserName());
            } else {
                try {
                    length = Double.parseDouble(lengthStr);
                } catch (NumberFormatException e) {
                    MesPcnException.throwMesBusiException("条码【%s】长度【%s】无效", lengthStr);
                }
                materialSnDb = new MesMaterialSn();
                ConvertBean.serviceModelInitialize(materialSnDb, model.getUserName());
                materialSnDb.setOrganizeCode(model.getOrganizeCode());
                materialSnDb.setSn(model.getSn());
                materialSnDb.setPartNo(partNo);
                materialSnDb.setLength(length);
                materialSnDb.setSurplusLength(length);
            }

            // 剩余需要扫描的长度
            Double surplusLength = MathOperation.sub(workOrderCutMaterial.getMaterialDosage(), workOrderCutMaterial.getScanLength());
            if (surplusLength.compareTo(length) > 0) {
                materialSnDb.setSurplusLength(0.0);
                workOrderCutMaterial.setScanLength(workOrderCutMaterial.getScanLength() + length);
                result.setIsRedirect(CommonEnumUtil.FALSE);
                result.setShowInfo("长度不足，请继续扫描条码");
                result.setIsReset(CommonEnumUtil.FALSE);
            } else {
                materialSnDb.setSurplusLength(MathOperation.sub(length, surplusLength));
                workOrderCutMaterial.setScanLength(workOrderCutMaterial.getMaterialDosage());

                boolean isUpdateWorkOrderCut = true;

                for (Map.Entry<String, MesWorkOrderCutMaterial> entry : workOrderCutMaterialMap.entrySet()) {
                    if (entry.getValue().getScanLength().compareTo(entry.getValue().getMaterialDosage()) != 0) isUpdateWorkOrderCut = false;
                }

                // 所有原材料已满足扫描总长度 则修改工单状态为已校验原材料并告知前端可重置页面
                if (isUpdateWorkOrderCut) {

                    workOrderCutRepository.updateByProperties(
                            new String[]{MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.CUT_WORK_ORDER_NO},
                            new Object[]{CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(),
                                    CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), model.getOrganizeCode(), model.getCutWorkOrderNo()},
                            new String[]{MesPcnExtConstWords.WORK_ORDER_STATUS, MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS},
                            new Object[]{MesExtEnumUtil.CUT_ORDER_STATUS.CHECKED_RAW.getValue(), model.getUserName(), TimeTool.getNowTime(true), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()});

                    result.setIsReset(CommonEnumUtil.VALID);
                } else result.setIsReset(CommonEnumUtil.FALSE);
                result.setIsRedirect(CommonEnumUtil.VALID);
            }

            MesCutModifyRawLengthRecord modifyRawLengthRecord = new MesCutModifyRawLengthRecord();
            ConvertBean.serviceModelInitialize(modifyRawLengthRecord, model.getUserName());
            modifyRawLengthRecord.setLength(materialSnDb.getLength());
            modifyRawLengthRecord.setSubLength(materialSnDb.getSurplusLength());
            modifyRawLengthRecord.setSn(model.getSn());
            modifyRawLengthRecord.setPartNo(materialSnDb.getPartNo());
            modifyRawLengthRecord.setCutWorkOrderNo(model.getCutWorkOrderNo());
            modifyRawLengthRecord.setType(MesExtEnumUtil.CUT_RAW_LENGTH_TYPE.ORDER.getValue());
            modifyRawLengthRecord.setOrganizeCode(model.getOrganizeCode());
            cutModifyRawLengthRecordRepository.save(modifyRawLengthRecord);

            ConvertBean.serviceModelUpdate(workOrderCutMaterial, model.getUserName());
            workOrderCutMaterialRepository.save(workOrderCutMaterial);
            ConvertBean.serviceModelUpdate(materialSnDb, model.getUserName());
            materialSnRepository.save(materialSnDb);

        }

        return result;
    }

    @Override
    public ListPager<MesWorkOrderCutMaterial> queryWorkOrderMaterialByPager(String cutWorkOrderNo, String organizeCode, Pager pager) {
        if (StringUtils.isEmpty(cutWorkOrderNo)) return new ListPager<>(new ArrayList<>(), pager);
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(cutWorkOrderNo, MesPcnExtConstWords.CUT_WORK_ORDER_NO, packBean);
        pager = PagerHelper.getPager(pager, workOrderCutMaterialRepository.findByHqlWhereCount(packBean));
        return new ListPager(workOrderCutMaterialRepository.findByHqlPage(packBean, pager), pager);
    }

    @Override
    public MesCutUpdateRawLengthModel queryLengthBySn(MesCutRawErrorProofingModel model) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(model.getSn(), MesPcnExtConstWords.SN, packBean);
        MesMaterialSn materialSnDb = materialSnRepository.getByProperty(packBean);
        if(Objects.isNull(materialSnDb))  MesPcnException.throwMesBusiException("条码【%s】不存在", model.getSn());
        MesCutUpdateRawLengthModel result = new MesCutUpdateRawLengthModel();
        BeanUtils.copyProperties(materialSnDb, result);
        return result;
    }

    @Override
    public void doUpdateLengthByScanSn(MesCutUpdateRawLengthModel model) {

        if (StringUtils.isEmpty(model.getSn())) return;

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(model.getSn(), MesPcnExtConstWords.SN, packBean);
        MesMaterialSn materialSnDb = materialSnRepository.getByProperty(packBean);

        if (materialSnDb == null) MesPcnException.throwMesBusiException("条码【%s】不存在", model.getSn());

        if (model.getSubLength() == null) MesPcnException.throwMesBusiException("条码【%s】未输入减去长度", model.getSn());

        if (materialSnDb.getSurplusLength() < model.getSubLength()) MesPcnException.throwMesBusiException("条码【%s】减去长度【%s】大于剩余长度【%s】", model.getSn(), materialSnDb.getSurplusLength(), model.getSubLength());

        materialSnDb.setSurplusLength(MathOperation.sub(materialSnDb.getSurplusLength(), model.getSubLength()));
        ConvertBean.serviceModelUpdate(materialSnDb, model.getUserName());
        materialSnRepository.save(materialSnDb);

        MesCutModifyRawLengthRecord modifyRawLengthRecord = new MesCutModifyRawLengthRecord();
        ConvertBean.serviceModelInitialize(modifyRawLengthRecord, model.getUserName());
        modifyRawLengthRecord.setLength(materialSnDb.getLength());
        modifyRawLengthRecord.setSubLength(materialSnDb.getSurplusLength());
        modifyRawLengthRecord.setSn(model.getSn());
        modifyRawLengthRecord.setModifyReason(model.getModifyReason());
        modifyRawLengthRecord.setType(MesExtEnumUtil.CUT_RAW_LENGTH_TYPE.OTHER.getValue());
        modifyRawLengthRecord.setOrganizeCode(model.getOrganizeCode());
        modifyRawLengthRecord.setPartNo(model.getPartNo());
        cutModifyRawLengthRecordRepository.save(modifyRawLengthRecord);

    }

    private List<MesWorkOrderCutMaterial> getWorkOrderCutMaterialList(MesCutRawErrorProofingModel model) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(model.getCutWorkOrderNo(), MesPcnExtConstWords.CUT_WORK_ORDER_NO, packBean);
        return workOrderCutMaterialRepository.findByHqlWhere(packBean);
    }

    private MesWorkOrderCut getMesWorkOrderCut(MesCutRawErrorProofingModel model) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(model.getSn(), MesPcnExtConstWords.CUT_WORK_ORDER_NO, packBean);
        return workOrderCutRepository.getByProperty(packBean);
    }
}
