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

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
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.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.PmSlabReplBt;
import com.xisc.pm.domain.repository.PmSlabReplBtRepository;
import com.xisc.pm.infra.constant.RuleSetConstants;
import com.xisc.pm.infra.enums.PdMatType;
import com.xisc.pm.infra.enums.PdRuleItemType;

import io.choerodon.core.exception.CommonException;
import lombok.extern.slf4j.Slf4j;

/**
 * 出钢记号匹配 （C01 , P06）
 * 
 * @author jun.zeng
 *
 */
@Slf4j
@Component
public class StNoRuleExecStrategy implements RuleExecStrategy {

    @Autowired
    private PmSlabReplBtRepository pmSlabReplBtRepository;
    
    @Autowired
    private ObjectMapper objectMapper;

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

    /**
     * 按合同上的内部钢种一个个匹配比较耗时，这里启用内存缓存
     * 按组板内部钢种查询所有的替代钢种
     * @param stNo
     * @param tenantId
     * @return
     */
    @SuppressWarnings("unchecked")
    private Set<String> getReplStNoCount(String stNo, Long tenantId) {
        String key = PdRuleItemType.ST_NO.name() + "." + stNo;
        String vuale = CACHE.getIfPresent(key);
        if(StringUtils.isBlank(vuale)) {
            List<PmSlabReplBt> pmSlabReplBts = pmSlabReplBtRepository.selectByCondition(Condition.builder(PmSlabReplBt.class)
                    .andWhere(Sqls.custom().andEqualTo(PmSlabReplBt.FIELD_TENANT_ID, tenantId)
                            .andEqualTo(PmSlabReplBt.FIELD_CUR_ST_NO, stNo)
                            .andEqualTo(PmSlabReplBt.FIELD_VALID_FLAG, BaseConstants.Flag.YES.toString()))
                    .build());
            Set<String> replStNo = new HashSet<>();
            replStNo.add(stNo);
            for (PmSlabReplBt pmSlabReplBt : pmSlabReplBts) {
                replStNo.add(pmSlabReplBt.getReplStNo());
            }
            try {
                CACHE.put(key, objectMapper.writeValueAsString(replStNo));
            } catch (JsonProcessingException e) {
                log.error(e.getMessage() , e);
            }
            return replStNo;
        } else {
            try {
                Set<String> replStNo = objectMapper.readValue(vuale, Set.class);
                return replStNo;
            } catch (JsonMappingException e) {
                log.error(e.getMessage() , e);
            } catch (JsonProcessingException e) {
                log.error(e.getMessage() , e);
            }
            return new HashSet<>() ;
        }
    }

    @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 matType = (String) bizData.get(RuleSetConstants.MAT_DESIGN_KIND);
        String stNoParam = (String) bizData.get(RuleSetConstants.ST_NO);

        PmContMscTech pmContMscTech = (PmContMscTech) bizData.get(RuleSetConstants.PM_CONT_MSC_TECH);
        if (pmContMscTech == null) {
            // 读生产合同池没有找到记录，合同号【order_no】，产线号【msc_line_no】
            throw new CommonException("pm.pm_pd_rule_set_001", orderNo, mscLineNo);
        }

        if (PdMatType.C.getCode().equals(matType)) {
            // 出钢材组板 TODO 
            
        } else if (PdMatType.P.getCode().equals(matType)) {
            // 余材组板 TODO 

        } else {
            // 余坯或者钢锭组板
            if (!pmContMscTech.getStNo().equals(stNoParam)) {
                Set<String> replStNo = getReplStNoCount(stNoParam, ruleParam.getTenantId());
                if(!replStNo.contains(pmContMscTech.getStNo())) {
                    // 合同【order_no】的内部钢种【ORDER_NO】与指定内部钢种【st_no】不匹配。
                    throw new CommonException("pm.pm_pd_rule_set_037", orderNo , pmContMscTech.getStNo() , stNoParam);
                }
            }
        }

        return true;
    }

}
