package com.xisc.pm.infra.repository.impl;

import com.google.common.collect.Lists;
import com.xisc.pm.api.dto.PmProContFilterRequestDTO;
import com.xisc.pm.api.dto.PmProContFilterResposeDTO;
import com.xisc.pm.api.dto.PmProContPoolRequestDTO;
import com.xisc.pm.api.dto.PmProContRequestDTO;
import com.xisc.pm.api.dto.PmProContSimpleDTO;
import com.xisc.pm.app.service.autoboard.dto.PmAutoBoardPolicyGroupDTO;
import com.xisc.pm.app.service.autoboard.dto.PmContBoardParam;
import com.xisc.pm.domain.entity.PmProCont;
import com.xisc.pm.domain.repository.PmProContRepository;
import com.xisc.pm.domain.vo.CtMainVO;
import com.xisc.pm.domain.vo.CtPrcPredPlanTimeVO;
import com.xisc.pm.domain.vo.QdToLineupResultSteelVO;
import com.xisc.pm.infra.constant.Constants;
import com.xisc.pm.infra.constant.PmPlateConstants;
import com.xisc.pm.infra.mapper.CtDetMapper;
import com.xisc.pm.infra.mapper.PmProContMapper;
import org.hzero.core.base.BaseConstants;
import org.hzero.mybatis.base.impl.BaseRepositoryImpl;
import org.hzero.mybatis.domian.Condition;
import org.hzero.mybatis.helper.BatchSqlHelper;
import org.hzero.mybatis.util.Sqls;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 生产合同主表 资源库实现
 *
 * @author 曾俊 jun.zeng@hand-china.com 2024-07-29 14:28:16
 */
@Component
public class PmProContRepositoryImpl extends BaseRepositoryImpl<PmProCont> implements PmProContRepository {

    @Autowired
    private PmProContMapper pmProContMapper;
    
    @Autowired
    private CtDetMapper ctDetMapper;

    @Override
    public PmProCont queryByOrderNo(String orderNo, Long tenantId) {
        PmProCont record = new PmProCont();
        record.setOrderNo(orderNo);
        record.setTenantId(tenantId);
        PmProCont result = this.selectOne(record);
        return result;
    }

    @Override
    public List<PmProCont> queryByOrderNoList(List<String> orderNoList, Long tenantId) {
        if (null != orderNoList && !orderNoList.isEmpty()) {
            return this.selectByCondition(Condition.builder(PmProCont.class).andWhere(Sqls.custom()
                    .andIn(PmProCont.FIELD_ORDER_NO, orderNoList).andEqualTo(PmProCont.FIELD_TENANT_ID, tenantId))
                    .build());
        }
        return new ArrayList<PmProCont>();
    }

    @Override
    public List<PmProCont> queryByOrderNoList(List<String> orderNoList, PmProContRequestDTO pmProContRequest) {
        pmProContRequest.setJoinCtMainFlag(BaseConstants.Flag.YES.longValue());
        return this.pmProContMapper.queryByOrderNoList(orderNoList, pmProContRequest);
    }

    @Override
    public int deleteByOrderNoList(List<String> orderNoList, Long tenantId) {
        if (null != orderNoList && !orderNoList.isEmpty()) {
            List<PmProCont> list = queryByOrderNoList(orderNoList, tenantId);
            return this.batchDeleteByPrimaryKey(list);
        }
        return 0;
    }

    @Override
    public List<PmProContFilterResposeDTO> orderFilterList(PmProContFilterRequestDTO pmProContFilterRequest) {
        return this.pmProContMapper.orderFilterList(pmProContFilterRequest);
    }
    
    @Override
    public List<PmProContSimpleDTO> selectProContSimpleList(Long tenantId , String orderNo , String stNo) {
        return this.pmProContMapper.selectProContSimpleList(tenantId, orderNo, stNo);
    }
    
    @Override
    public Map<String, PmProContFilterResposeDTO> orderFilterMap(List<String> orderNoList, Long tenantId,
            String mscLineNo) {
        Map<String, PmProContFilterResposeDTO> result = new HashMap<String, PmProContFilterResposeDTO>();
        long allCount = orderNoList.size();
        long limit = (allCount + PmPlateConstants.BATCH_MAX_SIZE - 1) / PmPlateConstants.BATCH_MAX_SIZE;
        Stream.iterate(0, n -> n + 1).limit(limit).forEach(i -> {
            // 分拆多个子sheet
            List<String> splitOrderNoList =  orderNoList.stream().skip(i * PmPlateConstants.BATCH_MAX_SIZE)
                    .limit(PmPlateConstants.BATCH_MAX_SIZE)
                    .collect(Collectors.toList());
            PmProContFilterRequestDTO contFilterRequestDTO = new PmProContFilterRequestDTO();
            contFilterRequestDTO.setOrderNoList(splitOrderNoList);
            contFilterRequestDTO.setMscLineNo(mscLineNo);
            contFilterRequestDTO.setTenantId(tenantId);
            List<PmProContFilterResposeDTO> filterList = this.orderFilterList(contFilterRequestDTO);
            if (filterList != null && !filterList.isEmpty()) {
                for (PmProContFilterResposeDTO pmProContFilterResposeDTO : filterList) {
                    result.put(pmProContFilterResposeDTO.getOrderNo(), pmProContFilterResposeDTO);
                }
            }
        });
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<PmProCont> createProContList(List<CtMainVO> ctMainVOs,
            PmProContPoolRequestDTO pmProContPoolRequestDTO , List<String> orderNoList) {
        if(ctMainVOs == null || ctMainVOs.isEmpty()) {
            return new ArrayList<>(1) ;
        }
        List<CtPrcPredPlanTimeVO> ctDetVOs = ctDetMapper.selectCtPrcPredPlanTime(pmProContPoolRequestDTO.getTenantId(),
                orderNoList, Lists.newArrayList(Constants.WholeBacklogCode.CODE_13 , Constants.WholeBacklogCode.CODE_14));
        Map<String , CtPrcPredPlanTimeVO> plan = new HashMap<>();
        Map<String , CtPrcPredPlanTimeVO> last = new HashMap<>();
        for (CtPrcPredPlanTimeVO ctDetVO : ctDetVOs) {
            if(Constants.WholeBacklogCode.CODE_13.equals(ctDetVO.getWholeBacklogCode())) {
                plan.put(ctDetVO.getOrderNo(), ctDetVO);
            } else {
                last.put(ctDetVO.getOrderNo(), ctDetVO);
            }
        }
        List<PmProCont> pmProConts = new ArrayList<>() ;
        for (CtMainVO ctMainVO : ctMainVOs) {
            // 调取合同跟踪模块“合同跟踪合同收池”接口，获取合同欠重量ORD_REM_WGT、合同欠件数ORD_REM_NUM、组板计划日期、最晚组板日期、炼钢计划日期、最晚炼钢日期
            PmProCont pmProCont = new PmProCont();
            pmProCont.setOrderNo(ctMainVO.getOrderNo());
            pmProCont.setOnPdFlag(BaseConstants.Flag.NO.longValue());
            CtPrcPredPlanTimeVO planCtDetVO = plan.get(ctMainVO.getOrderNo());
            CtPrcPredPlanTimeVO lastCtDetVO = last.get(ctMainVO.getOrderNo());
            if(planCtDetVO != null) {
                pmProCont.setPdPlanDate(planCtDetVO.getPlanEndDate()); 
                pmProCont.setPdLatestDate(planCtDetVO.getLatestEndDate());
            }
            if(lastCtDetVO != null) {
                pmProCont.setSteelPlanDate(lastCtDetVO.getPlanEndDate());
                pmProCont.setSteelLatestDate(lastCtDetVO.getLatestEndDate());
            }
            
            pmProCont.setPdHoldFlag(BaseConstants.Flag.NO.longValue());
            pmProCont.setPdLackQty(ctMainVO.getOrdRemNum());
            pmProCont.setPdLackWt(ctMainVO.getOrdRemWgt());
            pmProCont.setPdTotQty(BigDecimal.ZERO);
            pmProCont.setPdTotWt(BigDecimal.ZERO);
            pmProCont.setPdOverDevoQty(BigDecimal.ZERO);
            pmProCont.setPdOverDevoWt(BigDecimal.ZERO);
            pmProCont.setTenantId(pmProContPoolRequestDTO.getTenantId());
            pmProConts.add(pmProCont);
        }
        try {
            BatchSqlHelper.open();
            BatchSqlHelper.size(1000);
            return this.batchInsertSelective(pmProConts);
        } finally {
            BatchSqlHelper.clear();
        }
    }

    @Override
    public List<PmContBoardParam> selectAutoBoardContList(PmAutoBoardPolicyGroupDTO policyGroup, Long tenantId) {
        return pmProContMapper.selectAutoBoardContList(policyGroup, tenantId);
    }

    @Override
    public List<QdToLineupResultSteelVO> selectSlabPlaceCode(List<String> orderNoList, List<String> mscLineNoList, Long tenantId) {
        return pmProContMapper.selectSlabPlaceCode(orderNoList, mscLineNoList,  tenantId);
    }

    @Override
    public List<CtMainVO> queryOrderRemNumByOrderNoList(List<String> splitOrderNoList, Long tenantId) {
        return pmProContMapper.queryOrderRemNumByOrderNoList(splitOrderNoList,  tenantId);
    }

    @Override
    public List<PmProCont> selectByOrderList(List<String> orderNoList, Long tenantId) {
        return this.selectByCondition(Condition.builder(PmProCont.class)
                .andWhere(Sqls.custom().andIn(PmProCont.FIELD_ORDER_NO, orderNoList))
                .andWhere(Sqls.custom().andEqualTo(PmProCont.FIELD_TENANT_ID, tenantId))
                .build());
    }
}
