package cn.estsh.i3plus.ext.mes.apiservice.serviceimpl.base.jx;

import cn.estsh.i3plus.ext.mes.api.base.jx.IJxOqcProjectService;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesOqcRuleNoteDetail;
import cn.estsh.i3plus.ext.mes.pojo.bean.MesOqcRuleNoteDetailTravel;
import cn.estsh.i3plus.ext.mes.pojo.model.jx.JxOqcProjectModel;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesOqcRuleNoteDetailRepository;
import cn.estsh.i3plus.ext.mes.pojo.repository.MesOqcRuleNoteDetailTravelRepository;
import cn.estsh.i3plus.ext.mes.pojo.sqlpack.MesExtHqlPack;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtConstWords;
import cn.estsh.i3plus.ext.mes.pojo.util.MesExtEnumUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
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.MesPart;
import cn.estsh.i3plus.pojo.mes.repository.MesPartRepository;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
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;

/**
 * @author yumingxing
 * @version 1.0
 * @date 2021/2/5 15:42
 **/
@Service
public class JxOqcProjectService implements IJxOqcProjectService {

    @Autowired
    private MesOqcRuleNoteDetailRepository oqcProjectDao;

    @Autowired
    private MesOqcRuleNoteDetailTravelRepository oqcRuleNoteDetailTravelDao;

    @Autowired
    private MesPartRepository partRepository;

    private static final String ONE =  "1";
    private static final String TWO =  "2";
    private static final String THREE =  "3";
    private static final String FOUR =  "4";

    @Override
    public ListPager<JxOqcProjectModel> queryOqcProjectPager(MesOqcRuleNoteDetail oqcProject, Pager pager) {
        DdlPackBean hqlPack = MesExtHqlPack.getOqcProject(oqcProject);
        pager = PagerHelper.getPager(pager, oqcProjectDao.findByHqlWhereCount(hqlPack));
        hqlPack.setOrderByStr(" order by partNo asc, seq asc ");
        List<MesOqcRuleNoteDetail> oqcProjectList = oqcProjectDao.findByHqlWherePage(hqlPack, pager);
        List<JxOqcProjectModel> oqcProjectModels = new ArrayList<>();

        oqcProjectList.stream().forEach(sxQmsBuOqcProject -> {
            JxOqcProjectModel oqcProjectModel = new JxOqcProjectModel();
            BeanUtils.copyProperties(sxQmsBuOqcProject, oqcProjectModel);
            oqcProjectModel.setOqcNoTypeName(MesExtEnumUtil.OQC_CHECK_TYPE.valueOfDescription(oqcProjectModel.getOqcNoType()));
            oqcProjectModel.setCheckTypeName(MesExtEnumUtil.CHECK_JUDGE_TYPE.valueOfDescription(oqcProjectModel.getCheckType()));
            oqcProjectModels.add(oqcProjectModel);
        });

        return new ListPager(oqcProjectModels, pager);
    }

    @Override
    public void insertOqcProject(JxOqcProjectModel model) {

        if ((MesExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() == model.getOqcNoType() &&
                CollectionUtils.isEmpty(model.getPartNoList()))
                || (MesExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() != model.getOqcNoType() &&
                StringUtils.isEmpty(model.getCategoryCode3()))) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.PARAMETER_EXCEPTION.getCode())
                    .setErrorDetail("参数异常")
                    .build();
        }

        commCheckOqcProjectSeq(model.getSeq());

        MesOqcRuleNoteDetail oqcProjectDb = null;
        if (MesExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() == model.getOqcNoType()) {
            for (String partNo : model.getPartNoList()) {
                if (StringUtils.isEmpty(partNo)) {
                    continue;
                }
                oqcProjectDb = oqcProjectDao.getByProperty(
                        new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_DELETED, MesExtConstWords.OQC_NO_TYPE, MesExtConstWords.PART_NO, MesExtConstWords.CHECK_ITEM, MesExtConstWords.SEQ},
                        new Object[]{model.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), model.getOqcNoType(), partNo, model.getCheckItem(), model.getSeq()});
                if (null != oqcProjectDb) {
                    break;
                }
            }
        } else {
            oqcProjectDb = oqcProjectDao.getByProperty(
                    new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_DELETED, MesExtConstWords.OQC_NO_TYPE, MesExtConstWords.CATEGORY_CODE3, MesExtConstWords.CHECK_ITEM, MesExtConstWords.SEQ},
                    new Object[]{model.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), model.getOqcNoType(), model.getCategoryCode3(), model.getCheckItem(), model.getSeq()});
        }

        if (null != oqcProjectDb) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_EXIT.getCode())
                    .setErrorDetail("根据[检验单类型,物料或者产品类型,检验项目,序号]查询已经存在此条数据,请勿重复新增")
                    .build();
        }

        if(model.getCheckType() == MesExtEnumUtil.CHECK_JUDGE_TYPE.COMPARE_TYPE.getValue()){
            if (model.getBaseType() == null) model.setBaseType(MesExtEnumUtil.OQC_BASE_TYPE.DECIMALISM.getBase());
            checkCompareValueTypeIsValid(model);
        }else if(model.getCheckType() == MesExtEnumUtil.CHECK_JUDGE_TYPE.EQUIVALENCE_TYPE.getValue() && StringUtils.isEmpty(model.getStandardValue())){
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_EXIT.getCode())
                    .setErrorDetail("值类型为[等值类型],标准值不能为空")
                    .build();
        }

        if (MesExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() == model.getOqcNoType()) {
            for (String partNo : model.getPartNoList()) {
                if (StringUtils.isEmpty(partNo)) {
                    continue;
                }
                MesOqcRuleNoteDetail oqcProject = new MesOqcRuleNoteDetail();
                oqcProject.setPartNo(partNo);
                MesPart part = getPart(partNo, model.organizeCode);
                oqcProject.setCategoryCode3(part.getCategoryCode3());
                insertOqcProjectComm(oqcProject, model);
            }
        } else {
            MesOqcRuleNoteDetail oqcProject = new MesOqcRuleNoteDetail();
            oqcProject.setCategoryCode3(model.getCategoryCode3());
            insertOqcProjectComm(oqcProject, model);
        }
    }

    private void commCheckOqcProjectSeq(Double seq) {
        String[] seqArr = seq.toString().split(MesExtConstWords.DECIMAL_POINT);
        if (null != seqArr && seqArr.length == 2 && seqArr[1].length() > 1) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.PARAMETER_EXCEPTION.getCode())
                    .setErrorDetail("序号最多1位小数")
                    .build();
        }
    }

    private void insertOqcProjectComm(MesOqcRuleNoteDetail oqcProject, JxOqcProjectModel model) {
        oqcProject.setOqcNoType(model.getOqcNoType());
        oqcProject.setCheckItem(model.getCheckItem());
        oqcProject.setStandard(model.getStandard());
        oqcProject.setStandardValue(model.getStandardValue());
        oqcProject.setUpLimit(model.getUpLimit());
        oqcProject.setDownLimit(model.getDownLimit());
        oqcProject.setCheckType(model.getCheckType());
        oqcProject.setBaseType(model.getBaseType() == null ? MesExtEnumUtil.OQC_BASE_TYPE.DECIMALISM.getValue() : model.getBaseType());
        oqcProject.setModifyRemark(model.getModifyRemark());
        oqcProject.setCheckTool(model.getCheckTool());
        oqcProject.setSeq(model.getSeq());
        oqcProject.setOrganizeCode(model.getOrganizeCode());
        oqcProject.setSystemSyncStatus(MesExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(oqcProject, model.getCreateUser());
        oqcProjectDao.insert(oqcProject);
        // 新增出货检验项目履历
        insertOqcProjectTravel(oqcProject);
    }

    private void insertOqcProjectTravel(MesOqcRuleNoteDetail oqcProject){
        MesOqcRuleNoteDetailTravel sxQmsOqcRuleNoteDetailTravel = new MesOqcRuleNoteDetailTravel();
        BeanUtils.copyProperties(oqcProject, sxQmsOqcRuleNoteDetailTravel, MesExtConstWords.ID);
        ConvertBean.serviceModelInitialize(sxQmsOqcRuleNoteDetailTravel,oqcProject.getModifyUser());
        sxQmsOqcRuleNoteDetailTravel.setOrganizeCode(oqcProject.getOrganizeCode());
        oqcRuleNoteDetailTravelDao.insert(sxQmsOqcRuleNoteDetailTravel);
    }

    @Override
    public void updateOqcProject(JxOqcProjectModel model) {
        MesOqcRuleNoteDetail oqcProjectDb = oqcProjectDao.getById(model.getId());
        if (null == oqcProjectDb || CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue() == oqcProjectDb.getIsDeleted()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                    .setErrorDetail("ID[%s]数据不存在", model.getId())
                    .build();
        }

        commCheckOqcProjectSeq(model.getSeq());

        MesOqcRuleNoteDetail oqcProject;
        if (MesExtEnumUtil.OQC_CHECK_TYPE.DAILY_INSPECTION.getValue() == oqcProjectDb.getOqcNoType()) {
            oqcProject = oqcProjectDao.getByProperty(
                    new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_VALID, MesExtConstWords.IS_DELETED, MesExtConstWords.OQC_NO_TYPE, MesExtConstWords.PART_NO, MesExtConstWords.CHECK_ITEM, MesExtConstWords.SEQ},
                    new Object[]{model.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), oqcProjectDb.getOqcNoType(), oqcProjectDb.getPartNo(), model.getCheckItem(), model.getSeq()});
        } else {
            oqcProject = oqcProjectDao.getByProperty(
                    new String[]{MesExtConstWords.ORGANIZE_CODE, MesExtConstWords.IS_VALID, MesExtConstWords.IS_DELETED, MesExtConstWords.OQC_NO_TYPE, MesExtConstWords.CATEGORY_CODE3, MesExtConstWords.CHECK_ITEM, MesExtConstWords.SEQ},
                    new Object[]{model.getOrganizeCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), oqcProjectDb.getOqcNoType(), oqcProjectDb.getCategoryCode3(), model.getCheckItem(), model.getSeq()});
        }

        if (null != oqcProject && oqcProject.getId().compareTo(model.getId()) != 0) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_EXIT.getCode())
                    .setErrorDetail("根据[检验单类型,物料或者产品类型,检验项目,序号]查询已经存在此条数据,修改失败")
                    .build();
        }

        if(model.getCheckType() == MesExtEnumUtil.CHECK_JUDGE_TYPE.COMPARE_TYPE.getValue()){
            if (model.getBaseType() == null) model.setBaseType(MesExtEnumUtil.OQC_BASE_TYPE.DECIMALISM.getBase());
            checkCompareValueTypeIsValid(model);
        }

        oqcProjectDb.setCheckItem(model.getCheckItem());
        oqcProjectDb.setStandard(model.getStandard());
        oqcProjectDb.setUpLimit(model.getUpLimit());
        oqcProjectDb.setDownLimit(model.getDownLimit());
        oqcProjectDb.setStandardValue(model.getStandardValue());
        oqcProjectDb.setSeq(model.getSeq());
        oqcProjectDb.setCheckType(model.getCheckType());
        oqcProjectDb.setModifyRemark(model.getModifyRemark());
        oqcProjectDb.setBaseType(model.getBaseType());
        oqcProjectDb.setOrganizeCode(model.getOrganizeCode());
        oqcProjectDb.setCheckTool(model.getCheckTool());
        oqcProjectDb.setSystemSyncStatus(MesExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelUpdate(oqcProjectDb, model.getModifyUser());
        oqcProjectDao.save(oqcProjectDb);

        // 新增出货检验项目履历
        insertOqcProjectTravel(oqcProjectDb);
    }

    @Override
    public void updateOqcProjectValidById(JxOqcProjectModel model, String userName) {
        if (model.getStatus() != CommonEnumUtil.IS_VAILD.INVAILD.getValue() && model.getStatus() != CommonEnumUtil.IS_VAILD.VAILD.getValue()) {
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("启用，禁用枚举状态值[%s]未被定义", model.getStatus())
                    .build();
        }
        for (Long id : model.getIdList()) {
            if (StringUtils.isEmpty(id)) {
                continue;
            }
            MesOqcRuleNoteDetail oqcProjectDb = oqcProjectDao.getById(id);
            if (oqcProjectDb == null || CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue() == oqcProjectDb.getIsDeleted()) {
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.QMS.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
                        .setErrorDetail("ID[%s]记录不存在", id)
                        .build();
            }
            oqcProjectDao.updateByProperties(new String[]{MesExtConstWords.ID}, new Object[]{id},
                    new String[]{MesExtConstWords.SYSTEM_SYNC_STATUS, MesExtConstWords.IS_VALID, MesExtConstWords.MODIFY_USER, MesExtConstWords.MODIFY_DATE_TIME},
                    new Object[]{MesExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue(), model.getStatus(), userName, TimeTool.getNowTime(true)});
        }
    }

    /**
     * 异常
     * @param softTypeCode softTypeCode
     * @param errorDetailString 错误消息字符串
     * @param imppExceptionEnumCode 异常代码
     * @param args 参数
     */
    private void throwImppException(String softTypeCode, String errorDetailString, String imppExceptionEnumCode, Object... args) {
        throw ImppExceptionBuilder.newInstance()
                .setSystemID(softTypeCode)
                .setErrorCode(imppExceptionEnumCode)
                .setErrorDetail(errorDetailString,args)
                .build();
    }

    private Double baseConvertToDecimalism(String value, int baseOfValue) {
        return Double.valueOf(Integer.parseInt(value, MesExtEnumUtil.OQC_BASE_TYPE.baseOfValue(baseOfValue)));
    }

    private void checkCompareValueTypeIsValid(JxOqcProjectModel model){
        //标准值
        Double standardValue = null;
        //上限值
        Double upLimit = null;
        //下限值
        Double downLimit = null;
        if(!StringUtils.isEmpty(model.getStandardValue())){
            try {

                standardValue = baseConvertToDecimalism(model.getStandardValue(), model.getBaseType());

            } catch (NumberFormatException e) {
                throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "请输入数字");
            }
            String[] standard = model.getStandardValue().split(MesExtConstWords.DECIMAL_POINT);
            if (null != standard && standard.length == 2 && standard[1].length() > 3) {
                throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "最多三位小数");
            }
        }
        int num = 0;
        if(!StringUtils.isEmpty(model.getUpLimit())){
            try {
                upLimit = baseConvertToDecimalism(model.getUpLimit(), model.getBaseType());

            } catch (NumberFormatException e) {
                throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "请输入数字");
            }
            String[] standard = model.getUpLimit().split(MesExtConstWords.DECIMAL_POINT);
            if (null != standard && standard.length == 2 && standard[1].length() > 3) {
                throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "最多三位小数");
            }
        }else{
            num++;
        }

        if(!StringUtils.isEmpty(model.getDownLimit())){
            try {
                downLimit = baseConvertToDecimalism(model.getDownLimit(), model.getBaseType());
            } catch (NumberFormatException e) {
                throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "请输入数字");
            }
            String[] standard = model.getDownLimit().split(MesExtConstWords.DECIMAL_POINT);
            if (null != standard && standard.length == 2 && standard[1].length() > 3) {
                throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "最多三位小数");
            }
        }else{
            num++;
        }

        if(num == 2){
            throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.PARAMETER_EXCEPTION.getCode(), "上限值和下限值需至少有一位有值");
        }

        String computeType = null;
        if( downLimit != null && upLimit != null && standardValue != null){
            computeType = ONE;
        }else if(downLimit != null && standardValue != null){
            computeType = TWO;
        }else if(upLimit != null && standardValue != null){
            computeType = THREE;
        }else if(downLimit != null && upLimit != null){
            computeType = FOUR;
        }

        switch (computeType){
            case ONE:
                if(downLimit > standardValue || standardValue > upLimit || downLimit > upLimit){
                    throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.VARIFY_EXCEPTION.getCode(), "比值范围输入不合理");
                }
                break;
            case TWO:
                if(standardValue < downLimit){
                    throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.VARIFY_EXCEPTION.getCode(), "标准值小于下限值");
                }
                break;
            case THREE:
                if(standardValue > upLimit){
                    throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.VARIFY_EXCEPTION.getCode(), "标准值大于上限值");
                }
                break;
            case FOUR:
                if(downLimit > upLimit){
                    throwImppException(CommonEnumUtil.SOFT_TYPE.QMS.getCode(), ImppExceptionEnum.VARIFY_EXCEPTION.getCode(), "上限值小于下限值");
                }
        }
    }

    private MesPart getPart(String partNo, String organizeCode){
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(partNo, MesExtConstWords.PART_NO, packBean);
        return partRepository.getByProperty(packBean);
    }
}
