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

import com.xisc.pm.api.dto.PmCompositeBlockDTO;
import com.xisc.pm.api.dto.PmCompositeSlabCalcDTO;
import com.xisc.pm.api.dto.PmProContFilterResposeDTO;
import com.xisc.pm.api.dto.PmProContYieldDTO;
import com.xisc.pm.api.dto.PmProContYieldRequestDTO;
import com.xisc.pm.api.dto.PmSmallPlateDTO;
import com.xisc.pm.domain.entity.PmProContProdTtr;
import com.xisc.pm.domain.entity.PmSmallPltPos;
import com.xisc.pm.domain.repository.MmPlateRepository;
import com.xisc.pm.domain.repository.PmCutPlaceBtRepository;
import com.xisc.pm.domain.repository.PmPdTmpYieldBtRepository;
import com.xisc.pm.domain.repository.PmPlateCutLenBtRepository;
import com.xisc.pm.domain.repository.PmPlateTrimBtRepository;
import com.xisc.pm.domain.repository.PmQdToPoOrderRepository;
import com.xisc.pm.domain.repository.PmSlabScrapLenBtRepository;
import com.xisc.pm.domain.repository.PmSlabSpecBtRepository;
import com.xisc.pm.domain.repository.PmSmallPltPosRepository;
import com.xisc.pm.domain.repository.PmSpeStAddvBtRepository;
import com.xisc.pm.domain.repository.PmWmMatPileRepository;
import com.xisc.pm.infra.constant.PmPlateConstants;
import com.xisc.pm.infra.enums.FormPlateMode;
import com.xisc.pm.infra.util.BeanUtils;
import io.choerodon.core.exception.CommonException;
import org.apache.commons.lang3.StringUtils;
import org.hzero.core.base.BaseConstants;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 组板方式默认处理策略
 *
 * @author jun.zeng
 */
public abstract class DefaultFormPlateModeStrategy implements FormPlateModeStrategy {

    @Autowired
    protected PmCutPlaceBtRepository pmCutPlaceBtRepository;

    @Autowired
    protected PmSlabSpecBtRepository pmSlabSpecBtRepository;

    @Autowired
    protected PmPlateTrimBtRepository pmPlateTrimBtRepository;

    @Autowired
    protected PmPlateCutLenBtRepository pmPlateCutLenBtRepository;

    @Autowired
    protected PmSpeStAddvBtRepository pmSpeStAddvBtRepository;

    @Autowired
    protected PmQdToPoOrderRepository pmQdToPoOrderRepository;

    @Autowired
    protected PmSlabScrapLenBtRepository pmSlabScrapLenBtRepository;

    @Autowired
    protected PmWmMatPileRepository pmWmMatPileRepository;

    @Autowired
    protected MmPlateRepository mmPlateRepository;

    @Autowired
    protected PmPdTmpYieldBtRepository pmPdTmpYieldBtRepository;
    
    @Autowired
    protected PmSmallPltPosRepository pmSmallPltPosRepository;
    
    public PmCompositeBlockDTO getPmCompositeBlock(List<PmSmallPltPos> pmSmallPltPoss , Long blockNo) {
        pmSmallPltPoss.sort(new Comparator<PmSmallPltPos>() {
            @Override
            public int compare(PmSmallPltPos pos1, PmSmallPltPos pos2) {
                return pos1.getPickModeLenDir().compareTo(pos2.getPickModeLenDir());
            }
        });
        PmCompositeBlockDTO pmCompositeBloc = new PmCompositeBlockDTO();
        pmCompositeBloc.setBlkSpNum(pmSmallPltPoss.size());
        pmCompositeBloc.setBlockNo(blockNo.intValue());
        pmCompositeBloc.setBlockLength(BigDecimal.ZERO);
        pmCompositeBloc.setBlockWidth(BigDecimal.ZERO);
        List<PmSmallPlateDTO> smallPlateDTOList = new ArrayList<>();
        pmCompositeBloc.setSmallPlateDTOList(smallPlateDTOList);
        Map<String , Long> orderNoMap = new HashMap<String , Long>();
        for (PmSmallPltPos pmSmallPltPos : pmSmallPltPoss) {
            if(!orderNoMap.containsKey(pmSmallPltPos.getOrderNo())) {
                orderNoMap.put(pmSmallPltPos.getOrderNo(), 0L);
            }
            orderNoMap.put(pmSmallPltPos.getOrderNo(), orderNoMap.get(pmSmallPltPos.getOrderNo()) + 1L);
            pmCompositeBloc.setBlockLength(pmCompositeBloc.getBlockLength().add(pmSmallPltPos.getSmallPlateLen()));
            if(pmCompositeBloc.getBlockWidth().compareTo(pmSmallPltPos.getSmallPlateWidth()) <= 0) {
                pmCompositeBloc.setBlockWidth(pmSmallPltPos.getSmallPlateWidth());
            }
            PmSmallPlateDTO smallPlate = BeanUtils.copy(pmSmallPltPos, PmSmallPlateDTO.class);
            smallPlateDTOList.add(smallPlate);
            smallPlate.setBlockNo(blockNo);
            smallPlate.setPickModeLenDirPos(pmSmallPltPos.getPickModeLenDir().intValue());
            smallPlate.setPickModeWidDirPos(pmSmallPltPos.getPickModeWidDir().intValue());
        }
        for (PmSmallPlateDTO smallPlate : smallPlateDTOList) {
            smallPlate.setOrderBlockNum(orderNoMap.get(smallPlate.getOrderNo()));
        }
        pmCompositeBloc.setBlkOrderNum(orderNoMap.size());
        return pmCompositeBloc;
    }

    @Override
    public int maxOrderNum() {
        return PmPlateConstants.ORDER_COUNT;
    }

    /**
     * 获取取板方式枚举
     *
     * @param pmProContYield
     * @return
     */
    protected FormPlateMode getFormPlateMode(PmProContYieldRequestDTO pmProContYield) {
        return FormPlateMode.valueOf(pmProContYield.getPmContFilterRequest().getFormPlateMode());
    }

    /**
     * 检查组板小板
     *
     * @param smallPlate
     * @param orderContInfo
     * @param pmProContYieldDTO
     */
    protected void checkSmallPlateCount(PmSmallPlateDTO smallPlate, PmProContFilterResposeDTO orderContInfo, PmProContYieldDTO pmProContYieldDTO) {
        if(smallPlate.getSmallPlateLen().compareTo(smallPlate.getOrderLenMin()) < 0 || smallPlate.getSmallPlateLen().compareTo(smallPlate.getOrderLenMax()) > 0) {
            throw new CommonException("pm.pm_pro_cont_059" , smallPlate.getSmallPlateLen().toPlainString() , smallPlate.getOrderLenMin().toPlainString() , smallPlate.getOrderLenMax().toPlainString());
        }
    }
    
    /**
     * 检查组板小板数目与超投
     *
     * @param smallPlate
     * @param orderContInfo
     * @param pmProContYieldDTO
     */
    protected void checkOrderSpCount(PmProContFilterResposeDTO orderContInfo, PmProContYieldDTO pmProContYieldDTO , Map<String, BigDecimal> spCountByOrder) {
        BigDecimal pdOverDevoQty = pmProContYieldDTO.getPdOverDevoQty() == null ? BigDecimal.ZERO : pmProContYieldDTO.getPdOverDevoQty();
        // 合同欠件
        BigDecimal userdBoardNum = orderContInfo.getUserdBoardNum() == null ? BigDecimal.ZERO : orderContInfo.getUserdBoardNum();
        BigDecimal total = userdBoardNum.add(pdOverDevoQty);
        if (BigDecimal.ZERO.compareTo(pdOverDevoQty) < 0 && StringUtils.isBlank(pmProContYieldDTO.getPdOverDevoCause())) {
            // 超投件数大于零，必须输入超投原因
            throw new CommonException("pm.pm_pro_cont_040");
        }
        if(spCountByOrder == null || ! spCountByOrder.containsKey(pmProContYieldDTO.getOrderNo())) {
            return ;
        }
        if (!pmProContYieldDTO.isSkipCheckQty() && spCountByOrder.get(pmProContYieldDTO.getOrderNo()).compareTo(total) > 0) {
            // 合同组板数量不能大于欠件数+超投数
            if(BigDecimal.ZERO.compareTo(pdOverDevoQty) < 0) {
                throw new CommonException("pm.pm_pro_cont_065" , pmProContYieldDTO.getOrderNo(), pdOverDevoQty.toPlainString() , spCountByOrder.get(pmProContYieldDTO.getOrderNo()).toPlainString() , userdBoardNum.toPlainString() );
            } else {
                throw new CommonException("pm.pm_pro_cont_064" , pmProContYieldDTO.getOrderNo() , userdBoardNum.toPlainString() , spCountByOrder.get(pmProContYieldDTO.getOrderNo()).toPlainString());
            }
        }
        if (!pmProContYieldDTO.isSkipCheckQty() && BigDecimal.ZERO.compareTo(pdOverDevoQty) < 0 && spCountByOrder.get(pmProContYieldDTO.getOrderNo()).compareTo(total) != 0) {
            throw new CommonException("pm.pm_pro_cont_050");
        }
    }

    /**
     * 选中的合同列表 List->Map
     *
     * @param pmProContYield
     * @return
     */
    protected Map<String, PmProContYieldDTO> getPmProContYieldDTOMap(Map<String, PmProContFilterResposeDTO> filterOrderMap ,PmProContYieldRequestDTO pmProContYield) {
        Map<String, PmProContYieldDTO> map = new HashMap<>(pmProContYield.getPmProContYieldList().size());
        for (PmProContYieldDTO pmProContYieldDTO : pmProContYield.getPmProContYieldList()) {
            map.put(pmProContYieldDTO.getOrderNo(), pmProContYieldDTO);
            checkOrderSpCount(filterOrderMap.get(pmProContYieldDTO.getOrderNo()), pmProContYieldDTO, pmProContYield.getCompositeBoard().getOrderSpCount());
        }
        return map;
    }

    @Override
    public PmCompositeSlabCalcDTO checkAndInitParams(Map<String, PmProContFilterResposeDTO> filterOrderMap,
                                                     PmProContYieldRequestDTO pmProContYield, PmProContProdTtr axisPmProContProdTtr) {
        PmCompositeSlabCalcDTO pmCompositeSlabCalcDTO = new PmCompositeSlabCalcDTO();
        if (pmProContYield.getCompositeBoard().getBlkCount() > maxBlockNum()) {
            throw new CommonException("pm.pm_pro_cont_015", maxOrderNum(), maxBlockNum());
        }
        if (pmProContYield.getCompositeBoard().getOrderCount() > maxOrderNum()) {
            throw new CommonException("pm.pm_pro_cont_015", maxOrderNum(), maxBlockNum());
        }
        if (StringUtils.isNotBlank(axisPmProContProdTtr.getTrimCode()) && "0".equals(axisPmProContProdTtr.getTrimCode())
                && pmProContYield.getCompositeBoard().getSpCount() > 1) {
            // 一块大板上只能组一个小板！
            throw new CommonException("pm.pm_pro_cont_017");
        }
        // 获取工序记号类型
        if (StringUtils.isNotBlank(axisPmProContProdTtr.getBacklogQMark())
                && axisPmProContProdTtr.getBacklogQMark().charAt(0) == PmPlateConstants.BACKLOG_Q_MARK_FIRST_CHAR) {
            pmCompositeSlabCalcDTO.setType(PmPlateConstants.FUR_DEAL_TYPE_Q);
        } else if (StringUtils.isNotBlank(axisPmProContProdTtr.getBacklogTMark())
                && axisPmProContProdTtr.getBacklogTMark().charAt(0) == PmPlateConstants.BACKLOG_T_MARK_FIRST_CHAR) {
            pmCompositeSlabCalcDTO.setType(PmPlateConstants.FUR_DEAL_TYPE_Q);
        } else if (StringUtils.isNotBlank(axisPmProContProdTtr.getBacklogAMark())
                && axisPmProContProdTtr.getBacklogAMark().charAt(0) == PmPlateConstants.BACKLOG_A_MARK_FIRST_CHAR) {
            pmCompositeSlabCalcDTO.setType(PmPlateConstants.FUR_DEAL_TYPE_A);
        } else if (StringUtils.isNotBlank(axisPmProContProdTtr.getBacklogNMark())
                && axisPmProContProdTtr.getBacklogNMark().charAt(0) == PmPlateConstants.BACKLOG_N_MARK_FIRST_CHAR) {
            pmCompositeSlabCalcDTO.setType(PmPlateConstants.FUR_DEAL_TYPE_A);
        } else {
            pmCompositeSlabCalcDTO.setType(PmPlateConstants.FUR_DEAL_TYPE_G);
        }
        return pmCompositeSlabCalcDTO;
    }

    /**
     * 校验切边方式不能为‘S’ 轧制倍尺标记不能为0
     *
     * @param pmProContFilterResposeDTO
     */
    protected void checkCutModeAndMultiPlateFlag(PmProContFilterResposeDTO pmProContFilterResposeDTO) {
        if (pmProContFilterResposeDTO.getPlanerFlag() != null && BaseConstants.Flag.NO.toString().equals(pmProContFilterResposeDTO.getPlanerFlag())) {
            // 轧制倍尺标记不能为0
            throw new CommonException("pm.pm_pro_cont_055", pmProContFilterResposeDTO.getOrderNo());
        }
        if (PmPlateConstants.CUT_MODE_S.equals(pmProContFilterResposeDTO.getCutModeCode())) {
            // 切断方式不能为‘S’
            throw new CommonException("pm.pm_pro_cont_054" , pmProContFilterResposeDTO.getOrderNo());
        }
    }
}
