package com.prolog.eis.service.bindgridex.impl;

import com.prolog.eis.constants.sys.SysParamConstants;
import com.prolog.eis.dao.out.BizOutboundTaskMapper;
import com.prolog.eis.dao.out.shelves.GridInfoMapper;
import com.prolog.eis.dto.bindgridex.BGDExGridDto;
import com.prolog.eis.dto.bindgridex.BGDExDispatchDto;
import com.prolog.eis.dto.bindgridex.BGDExOrderDto;
import com.prolog.eis.service.bindgridex.BindGridExInitService;
import com.prolog.eis.service.sys.SysParamService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Version: 1.0
 * @Author: wuhan
 * @Created: 2024/8/1 15:38
 */
@Service
public class BindGridExInitServiceImpl implements BindGridExInitService {
    @Resource
    private GridInfoMapper gridInfoMapper;

    @Resource
    private BizOutboundTaskMapper bizOutboundTaskMapper;

    @Resource
    private SysParamService sysParamService;

    @Override
    public BGDExDispatchDto init() throws Exception {
        BGDExDispatchDto dispatchDto = new BGDExDispatchDto();

        List<BGDExGridDto> gridList = gridInfoMapper.queryBGDExGridList();
        dispatchDto.setGridList(gridList);

        int freeGridCount = (int) gridList.stream().filter(r -> r.getBindOrderId() == null || r.getBindOrderId() == 0).count();
        //如果没有空闲格口，则不进行绑定逻辑
        if (freeGridCount <= 0) {
            return null;
        }

        List<BGDExOrderDto> noBindOrderList = bizOutboundTaskMapper.queryNotBindOrders();
        String bestWaveNo = this.findBestBindWaveNo(noBindOrderList);
        if (bestWaveNo == null) {
            return null;
        }

        //获得最小波次的所有未绑定订单
        List<BGDExOrderDto> bestWaveOrderList = noBindOrderList.stream().filter(r -> r.getWaveNo().equals(bestWaveNo)).collect(Collectors.toList());
        //检查最小波次号是否已经绑定过订单
        boolean hasBestWaveBind = this.checkBestWaveNoBind(gridList, bestWaveNo);
        //计算最小波次能绑定的订单数
        int waveBindOrderCount = this.queryWaveBindMaxOrderCount(freeGridCount, bestWaveOrderList.size(), hasBestWaveBind);
        if (waveBindOrderCount <= 0) {
            return null;
        }

        //截取可绑定订单，如果该波次订单数大于单次最大绑定数则取该值的订单,否则取剩余所有订单
        List<BGDExOrderDto> bestOrderList = this.findSubOrderList(bestWaveOrderList, waveBindOrderCount);
        dispatchDto.setOrderList(bestOrderList);

        dispatchDto.init();
        return dispatchDto;
    }

    /**
     * 检查一个波次是否未绑定
     */
    private boolean checkBestWaveNoBind(List<BGDExGridDto> gridList, String bestWaveNo) {
        for (BGDExGridDto grid : gridList) {
            if (grid.getWaveNo() != null && grid.getWaveNo().equals(bestWaveNo)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取最大绑定订单数
     * @param freeGridCount
     * @param orderCount
     * @param hasBestWaveBind
     * @return
     */
    private int queryWaveBindMaxOrderCount(int freeGridCount, int orderCount, boolean hasBestWaveBind) {
        String waveBindMaxOrderCountStr = sysParamService.findVal(SysParamConstants.WAVE_BIND_MAX_ORDER_COUNT, "110");
        int waveBindMaxOrderCount = Integer.parseInt(waveBindMaxOrderCountStr);
        if (waveBindMaxOrderCount > SysParamConstants.TOTAL_GRID_COUNT) {
            waveBindMaxOrderCount = SysParamConstants.TOTAL_GRID_COUNT;
        }

        if (hasBestWaveBind) {
            //如果是已经绑定的波次，则将剩余空闲格口尽可能全部绑定
            if (freeGridCount < orderCount) {
                return freeGridCount;
            } else {
                return orderCount;
            }
        } else {
            //如果是新绑定波次，则需要达到新波次绑定订单数才能绑定订单
            if (freeGridCount > waveBindMaxOrderCount) {
                //如果空闲格口超过新波次绑定订单数，则将空闲格口全部绑满（一般在当天作业的第一个波次出现）
                return freeGridCount;
            } else {
                return waveBindMaxOrderCount;
            }
        }
    }

    /**
     * 获取一个订单集合的制定数量的子订单集合
     * @param orderList
     * @param maxOrderCount
     * @return
     */
    private List<BGDExOrderDto> findSubOrderList(List<BGDExOrderDto> orderList, int maxOrderCount) {
        if (orderList.size() > maxOrderCount) {
            List<BGDExOrderDto> sortOrderList = orderList.stream().sorted(Comparator.comparing(BGDExOrderDto::getDetailCount, Comparator.reverseOrder())).collect(Collectors.toList());
            return sortOrderList.subList(0, maxOrderCount);
        } else {
            return orderList;
        }
    }

    /**
     * 查询未绑定订单的最小波次号
     * @param noBindOrderList
     * @return
     */
    private String findBestBindWaveNo(List<BGDExOrderDto> noBindOrderList) {
        String bestWaveNo = null;
        for (BGDExOrderDto order : noBindOrderList) {
            if (bestWaveNo == null) {
                bestWaveNo = order.getWaveNo();
                continue;
            }
            //如果波次号都没绑定，则选择最小波次号
            if (order.getWaveNo().compareTo(bestWaveNo) < 0) {
                bestWaveNo = order.getWaveNo();
                continue;
            }
        }
        return bestWaveNo;
    }
}
