package com.xisc.pm.app.service.strategy.pdrule;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hzero.core.base.BaseConstants;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xisc.pm.api.dto.RuleParamDTO;
import com.xisc.pm.app.service.strategy.RuleExecStrategyFactory;
import com.xisc.pm.domain.entity.PmContMscTech;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSdivStLimitBt;
import com.xisc.pm.domain.repository.PmSdivStLimitBtRepository;
import com.xisc.pm.infra.constant.PmPlateConstants;
import com.xisc.pm.infra.constant.RuleSetConstants;
import com.xisc.pm.infra.enums.FormPlateMode;
import com.xisc.pm.infra.enums.PdRuleItemType;

import io.choerodon.core.exception.CommonException;

/**
 * 剖分组板钢种限制检查校验
 * 
 * 对传入的组板方式form_plate_mode，若其为A型组板，则通过校验。
 * 根据内部钢种st_no，标准牌号sg_sign，板坯厚度mold_thick，板坯宽度mold_width，
 * 读取剖分组板钢种限制表PM_SDIV_ST_LIMIT_BT，查询条件包括： 
 * 内部钢种，标准牌号（若基表值为*，则匹配任意标准牌号），板坯厚度起止包含mold_thick， 板坯宽度起止包含mold_width，生效标记为是。
 * 若能查到记录，校验不通过，返回消息：组板结果受剖分组板限制，不能组板。组板方式【form_plate_mode】，
 * 内部钢种【st_no】，外部牌号【sg_sign】，板坯厚度【mold_thick】，板坯宽度【mold_width】.
 * 
 * 
 * @author jun.zeng
 *
 */
@Component
public class CombineStNoLimitRuleExecStrategy implements RuleExecStrategy {

    @Autowired
    private PmSdivStLimitBtRepository pmSdivStLimitBtRepository;

    @Override
    public void afterPropertiesSet() throws Exception {
        RuleExecStrategyFactory.register(PdRuleItemType.COMBINE_ST_NO_LIMIT, this);
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean execRule(RuleParamDTO ruleParam) {
        Map<String, Object> bizData = ruleParam.getBizData();
        String orderNo = (String) bizData.get(RuleSetConstants.ORDER_NO);
        String mscLineNo = (String) bizData.get(RuleSetConstants.MSC_LINE_NO);
        String formPlateModeValue = (String) bizData.get(RuleSetConstants.FORM_PLATE_MODE);
        BigDecimal moldThick = (BigDecimal) bizData.get(RuleSetConstants.MOLD_THICK);
        BigDecimal moldWidth = (BigDecimal) bizData.get(RuleSetConstants.MOLD_WIDTH);
        FormPlateMode formPlateMode = FormPlateMode.getByCode(formPlateModeValue);
        if (FormPlateMode.A1.getType().equals(formPlateMode.getType())) {
            // A型组板直接通过
            return true;
        }
        List<PmContMscTech> pmContMscTechList = (List<PmContMscTech>) bizData
                .get(RuleSetConstants.PM_CONT_MSC_TECH_LIST);
        List<PmProContProdTtr> pmProContProdTtrList = (List<PmProContProdTtr>) bizData
                .get(RuleSetConstants.PM_PRO_CONT_PROD_ATTR_LIST);

        PmContMscTech pmContMscTechParam = (PmContMscTech) bizData.get(RuleSetConstants.PM_CONT_MSC_TECH);
        PmProContProdTtr pmProContProdTtrParam = (PmProContProdTtr) bizData.get(RuleSetConstants.PM_PRO_CONT_PROD_ATTR);

        if ((pmContMscTechList == null || pmContMscTechList.isEmpty()) && pmContMscTechParam == null) {
            throw new CommonException("pm.pm_pd_rule_set_001", orderNo, mscLineNo);
        }
        if (pmContMscTechParam != null && pmProContProdTtrParam != null) {
            List<String> sgSginList = new ArrayList<String>();
            sgSginList.add(pmProContProdTtrParam.getSgSign());
            sgSginList.add(PmPlateConstants.ALL);
            int count = pmSdivStLimitBtRepository.selectCountByCondition(Condition.builder(PmSdivStLimitBt.class)
                    .andWhere(Sqls.custom().andEqualTo(PmSdivStLimitBt.FIELD_ST_NO, pmContMscTechParam.getStNo())
                            .andLessThanOrEqualTo(PmSdivStLimitBt.FIELD_VALID_FLAG, BaseConstants.Flag.YES.toString())
                            .andIn(PmSdivStLimitBt.FIELD_SG_SIGN,sgSginList )
                            .andLessThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_THICK_FROM, moldThick)
                            .andLessThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_WIDTH_FROM, moldWidth)
                            .andGreaterThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_WIDTH_TO, moldWidth)
                            .andGreaterThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_THICK_TO, moldThick)
                            .andEqualTo(PmSdivStLimitBt.FIELD_TENANT_ID, ruleParam.getTenantId()))
                    .build());
            if (count > 0) {
                // 组板结果受剖分组板限制，不能组板。组板方式【form_plate_mode】，内部钢种【st_no】，外部牌号【sg_sign】，板坯厚度【mold_thick】，板坯宽度【mold_width】
                throw new CommonException("pm.pm_pd_rule_set_043", formPlateMode, pmContMscTechParam.getStNo(),
                        pmProContProdTtrParam.getSgSign(), moldThick.toPlainString(), moldWidth.toPlainString());
            }
        } 
        if (pmContMscTechList != null && !pmContMscTechList.isEmpty() && pmProContProdTtrList != null && !pmProContProdTtrList.isEmpty()) {
            Map<String, String> pmContMscTechMap = new HashMap<String, String>();
            Set<String> stNoList = new HashSet<>();
            for (PmContMscTech pmContMscTech : pmContMscTechList) {
                stNoList.add(pmContMscTech.getStNo());
                pmContMscTechMap.put(pmContMscTech.getOrderNo(), pmContMscTech.getStNo());
            }
            // 查询所有满足条件的配置
            List<PmSdivStLimitBt> pmSdivStLimitBtList = pmSdivStLimitBtRepository.selectByCondition(Condition.builder(PmSdivStLimitBt.class)
                    .andWhere(Sqls.custom().andIn(PmSdivStLimitBt.FIELD_ST_NO, stNoList)
                            .andLessThanOrEqualTo(PmSdivStLimitBt.FIELD_VALID_FLAG, BaseConstants.Flag.YES.toString())
                            .andLessThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_THICK_FROM, moldThick)
                            .andLessThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_WIDTH_FROM, moldWidth)
                            .andGreaterThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_WIDTH_TO, moldWidth)
                            .andGreaterThanOrEqualTo(PmSdivStLimitBt.FIELD_SLAB_THICK_TO, moldThick)
                            .andEqualTo(PmSdivStLimitBt.FIELD_TENANT_ID, ruleParam.getTenantId()))
                    .build());
            Set<String> checkSet = new HashSet<>();
            for (PmSdivStLimitBt pmSdivStLimitBt : pmSdivStLimitBtList) {
                checkSet.add(pmSdivStLimitBt.getStNo() + "-" + pmSdivStLimitBt.getSgSign());
            }
            if(pmProContProdTtrList != null) {
                for (PmProContProdTtr pmProContProdTtr : pmProContProdTtrList) {
                    String stNo = pmContMscTechMap.get(pmProContProdTtr.getOrderNo());
                    if(checkSet.contains(stNo + "-*") || checkSet.contains(stNo + "-" + pmProContProdTtr.getSgSign())) {
                     // 组板结果受剖分组板限制，不能组板。组板方式【form_plate_mode】，内部钢种【st_no】，外部牌号【sg_sign】，板坯厚度【mold_thick】，板坯宽度【mold_width】
                        throw new CommonException("pm.pm_pd_rule_set_043", formPlateMode, stNo,
                                pmProContProdTtr.getSgSign(), moldThick.toPlainString(), moldWidth.toPlainString());
                    }
                }
            }
        }
        return true;
    }

}
