package com.shkj.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.shkj.common.annotation.DataScopeConsignor;
import com.shkj.common.constant.HttpStatus;
import com.shkj.common.core.domain.Result;
import com.shkj.common.core.domain.entity.BaseBranch;
import com.shkj.common.enums.IsDelEnum;
import com.shkj.common.utils.SecurityUtils;
import com.shkj.common.utils.StringUtils;
import com.shkj.common.utils.bean.BeanValidators;
import com.shkj.system.service.IBaseBranchService;
import com.shkj.wms.bo.*;
import com.shkj.wms.config.ValidList;
import com.shkj.wms.domain.BaseArea;
import com.shkj.wms.domain.BaseLocation;
import com.shkj.wms.enums.DeleteFlagEnum;
import com.shkj.wms.enums.YesAndNoEnum;
import com.shkj.wms.mapper.BaseLocationMapper;
import com.shkj.wms.service.*;
import com.shkj.wms.utils.BeanMapperUtils;
import com.shkj.wms.utils.TunnelTaskUtil;
import com.shkj.wms.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Validator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 货位资料Service业务层处理
 *
 * @author lch
 * @date 2022-04-23
 */
@Slf4j
@Service
public class BaseLocationServiceImpl extends ServiceImpl<BaseLocationMapper, BaseLocation> implements IBaseLocationService {

    @Autowired
    private ISysBatchService sysBatchService;

    @Autowired
    protected Validator validator;

    @Autowired
    private IBaseAreaService iBaseAreaService;

    @Autowired
    private IBaseStorageService baseStorageService;

    @Autowired
    private IBaseBranchService baseBranchService;

    @Autowired
    private ISysStockDetailService iSysStockDetailService;

    @Override
    public Result<BaseLocationVo> queryById(Long id) {
        BaseLocation db = this.baseMapper.selectById(id);
        BaseLocationVo vo = BeanUtil.toBean(db, BaseLocationVo.class);
        return Result.ok().data(vo);
    }

    @Override
    public List<BaseLocationVo> queryList(BaseLocationQueryBo bo) {
        LambdaQueryWrapper<BaseLocation> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getLocationCode()), BaseLocation::getLocationCode, bo.getLocationCode());
        lqw.like(StrUtil.isNotBlank(bo.getLocationName()), BaseLocation::getLocationName, bo.getLocationName());
        lqw.eq(bo.getAreaId() != null, BaseLocation::getAreaId, bo.getAreaId());
        lqw.eq(StrUtil.isNotBlank(bo.getType()), BaseLocation::getType, bo.getType());
        lqw.eq(StrUtil.isNotBlank(bo.getTunnel()), BaseLocation::getTunnel, bo.getTunnel());
        lqw.eq(StrUtil.isNotBlank(bo.getLocationRow()), BaseLocation::getLocationRow, bo.getLocationColumn());
        lqw.eq(StrUtil.isNotBlank(bo.getLayer()), BaseLocation::getLayer, bo.getLayer());
        lqw.eq(StrUtil.isNotBlank(bo.getLocationColumn()), BaseLocation::getLocationColumn, bo.getLocationColumn());
        lqw.eq(StrUtil.isNotBlank(bo.getIsuse()), BaseLocation::getIsuse, bo.getIsuse());
        lqw.eq(bo.getLength() != null, BaseLocation::getLength, bo.getLength());
        lqw.eq(bo.getWidth() != null, BaseLocation::getWidth, bo.getWidth());
        lqw.eq(bo.getHeight() != null, BaseLocation::getHeight, bo.getHeight());
        lqw.eq(bo.getVolume() != null, BaseLocation::getVolume, bo.getVolume());
        lqw.eq(bo.getWeight() != null, BaseLocation::getWeight, bo.getWeight());
        lqw.eq(bo.getCapacity() != null, BaseLocation::getCapacity, bo.getCapacity());
        lqw.eq(bo.getSkunum() != null, BaseLocation::getSkunum, bo.getSkunum());
        lqw.eq(StrUtil.isNotBlank(bo.getLocationGroup()), BaseLocation::getLocationGroup, bo.getLocationGroup());
        lqw.eq(StrUtil.isNotBlank(bo.getLogicArea()), BaseLocation::getLogicArea, bo.getLogicArea());
        lqw.eq(StrUtil.isNotBlank(bo.getAbcClassify()), BaseLocation::getAbcClassify, bo.getAbcClassify());
        lqw.eq(StrUtil.isNotBlank(bo.getFloor()), BaseLocation::getFloor, bo.getFloor());
        lqw.eq(StrUtil.isNotBlank(bo.getStorageConditions()), BaseLocation::getStorageConditions, bo.getStorageConditions());
        lqw.eq(StrUtil.isNotBlank(bo.getRoute()), BaseLocation::getRoute, bo.getRoute());
        lqw.eq(StrUtil.isNotBlank(bo.getStorageClassify()), BaseLocation::getStorageClassify, bo.getStorageClassify());
        lqw.eq(StrUtil.isNotBlank(bo.getExtend1()), BaseLocation::getExtend1, bo.getExtend1());
        lqw.eq(StrUtil.isNotBlank(bo.getExtend2()), BaseLocation::getExtend2, bo.getExtend2());
        lqw.eq(StrUtil.isNotBlank(bo.getExtend3()), BaseLocation::getExtend3, bo.getExtend3());
        lqw.eq(StrUtil.isNotBlank(bo.getExtend4()), BaseLocation::getExtend4, bo.getExtend4());
        lqw.eq(StrUtil.isNotBlank(bo.getExtend5()), BaseLocation::getExtend5, bo.getExtend5());
        lqw.eq(bo.getBranchId() != null, BaseLocation::getBranchId, bo.getBranchId());
        lqw.eq(StrUtil.isNotBlank(bo.getIsDel()), BaseLocation::getIsDel, bo.getIsDel());
        lqw.eq(StrUtil.isNotBlank(bo.getIsDeep()), BaseLocation::getIsDeep, bo.getIsDeep());
        lqw.eq(BaseLocation::getIsDel, IsDelEnum.NORMAL.getValue());
        lqw.orderByDesc(BaseLocation::getCreateTime);
        List<BaseLocationVo> voList = entity2Vo(this.list(lqw));
        return voList;

    }

    /**
     * 实体类转化成视图对象
     *
     * @param collection 实体类集合
     * @return
     */
    private List<BaseLocationVo> entity2Vo(Collection<BaseLocation> collection) {
        List<BaseLocationVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, BaseLocationVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<BaseLocation> page = (Page<BaseLocation>) collection;
            Page<BaseLocationVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page, pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> insertByAddBo(BaseLocationAddBo bo) {
        BaseLocation add = BeanUtil.toBean(bo, BaseLocation.class);
        this.save(add);
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> updateByEditBo(BaseLocationEditBo bo) {
        BaseLocation one = getById(bo.getId());
        if (one == null) {
            return Result.err().msg("不存在");
        }
        BaseLocation update = BeanUtil.toBean(bo, BaseLocation.class);
        this.updateById(update);
        return Result.ok();
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> deleteWithValidById(List<Long> ids, Boolean isValid) {
        BaseLocation del = new BaseLocation();
        del.setIsDel(IsDelEnum.DELETED.getValue());
        LambdaQueryWrapper<BaseLocation> wrapper = new LambdaQueryWrapper<BaseLocation>().in(BaseLocation::getId, ids)
                .eq(BaseLocation::getBranchId, SecurityUtils.getCurrentBranchId());
        this.update(del, wrapper);
        return Result.ok();
    }


    /**
     * 根据id集合查询货位信息
     *
     * @param locationIds
     * @return
     */
    @Override
    public List<BaseLocationVo> queryLocationsByIds(List<Long> locationIds) {
        return this.baseMapper.queryLocationsByIds(locationIds);
    }

    /**
     * 根据id集合查询货位信息
     *
     * @param locationIds
     * @param goodsId
     * @return
     */
    @Override
    public List<BaseLocationVo> queryLocationsPackageByIds(List<Long> locationIds, Long goodsId) {
        return this.baseMapper.queryLocationsPackageByIds(locationIds, goodsId);
    }

    /**
     * 查询货位资料列表
     *
     * @param bo
     * @return
     */
    @Override
    @DataScopeConsignor(branchAlias = "bl")
    public List<BaseLocationVo> queryBaseLocationList(BaseLocationQueryPageBo bo) {
        List<BaseLocationVo> list = this.getBaseMapper().queryBaseLocationList(bo);
//        list.forEach(s -> {
//            BaseAreaQueryBo areaBo = BeanUtil.toBean(bo, BaseAreaQueryBo.class);
//            areaBo.setStorageId(s.getStorageId());
//            s.setAreaVoList(iBaseAreaService.queryList(areaBo));
//        });
        return list;
    }

    @Override
    @DataScopeConsignor(branchAlias = "bl")
    public List<String> queryBaseLocationTunnelList(BaseLocationQueryListBo bo) {
        BaseLocationQueryPageBo boo = BeanUtil.toBean(bo, BaseLocationQueryPageBo.class);
        List<BaseLocationVo> list = this.getBaseMapper().queryBaseLocationList(boo);
        List<String> listTunnel = list.stream().map(b -> b.getTunnel()).distinct().collect(Collectors.toList());
        return listTunnel;
    }

    /**
     * 根据ids获取区域数据
     *
     * @param ids
     * @return
     */
    public List<BaseLocation> queryBaseLocationByIds(List<Long> ids) {
        LambdaQueryWrapper<BaseLocation> wrapper = new LambdaQueryWrapper<BaseLocation>()
                .in(BaseLocation::getId, ids)
                .eq(BaseLocation::getBranchId, SecurityUtils.getCurrentBranchId())
                .eq(BaseLocation::getIsDel, DeleteFlagEnum.NORMAL.getValue());
        return this.list(wrapper);
    }


    /**
     * 保存或者修改货位资料列表（根据是否有id来判断新增或者修改）
     *
     * @param list
     * @return
     */
    @Override
    public Result<Boolean> saveOrUpdateBaseLocations(ValidList<BaseLocationSaveOrUpdateBo> list) {
        List<BaseLocation> addList = new ArrayList<>();
        List<BaseLocation> updList = new ArrayList<>();
        // 参数校验
        Result<Boolean> resultBo = checkBaseLocationSaveOrUpdateBo(list);
        if (!Result.isOk(resultBo)) {
            return resultBo;
        }
        for (BaseLocationSaveOrUpdateBo bo : list) {
            bo.setIsuse(StringUtils.isBlank(bo.getIsuse()) ? YesAndNoEnum.YES.getValue() : bo.getIsuse());
            if (bo.getId() != null) {
                BaseLocation update = BeanUtil.toBean(bo, BaseLocation.class);
                Result result = checkEntity(update);
                if (!Result.isOk(result)) {
                    return Result.err().msg(result.getMsg());
                }
                updList.add(update);
            } else {
                BaseLocation add = BeanUtil.toBean(bo, BaseLocation.class);
                Result result = checkEntity(add);
                if (!Result.isOk(result)) {
                    return Result.err().msg(result.getMsg());
                }
                addList.add(add);
            }
        }
        this.updateBatchById(updList);
        this.saveBatch(addList);
        return Result.ok();
    }

    private Result<Boolean> checkBaseLocationSaveOrUpdateBo(ValidList<BaseLocationSaveOrUpdateBo> list) {
        // 首先校验请求参数是否出现重复
        boolean b = list.stream().filter(x -> !StringUtils.isNumeric(x.getRoute())).findFirst().isPresent();
        if (b) {
            return Result.err().msg("拣货路径异常");
        }
//        // 显示货位是否重复
//        List<String> listLocationNames = list.stream().map(s -> s.getLocationName()).distinct().collect(Collectors.toList());
//        if (CollectionUtils.isEmpty(listLocationNames)
//                || listLocationNames.size() != list.size()) {
//            return Result.err().msg("货位名称重复");
//        }
        // 货位id是否重复
        List<String> listLocationCodes = list.stream().map(
                s -> (s.getTunnel() + "-"
                        + s.getLocationRow()
                        + s.getLocationColumn()
                        + s.getLayer() + "-"
                        + s.getIsDeep()
                )).distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(listLocationCodes)
                || listLocationCodes.size() != list.size()) {
            return Result.err().msg("根据规则货位排层列重复");
        }
        // 库区资料
        List<Long> listAreaIds = list.stream().map(s -> s.getAreaId()).distinct().collect(Collectors.toList());
        List<BaseArea> baseAreaList = iBaseAreaService.listByIds(listAreaIds);
        if (CollectionUtils.isEmpty(baseAreaList) || baseAreaList.size() != listAreaIds.size()) {
            return Result.err().msg("库区资料存在异常");
        }
        // 修改的数据
        List<Long> listLocationIds = list.stream().filter(s -> s.getId() != null).map(s -> s.getId()).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(listLocationIds)) {
            List<BaseLocation> baseLocations = listByIds(listLocationIds);
            if (CollectionUtils.isEmpty(baseLocations) ||
                    listLocationIds.size() != baseLocations.size()) {
                return Result.err().msg("存在货位资料不存在的数据");
            }
        }
        return Result.ok();
    }

    @Override
    public Result<Boolean> saveBaseLocationMany(BaseLocationManyBo bo) {

        List<BaseLocation> addList = new ArrayList<>();

        if (bo.getStartLocationRow() < 0L || bo.getEndLocationRow() < 0L || bo.getStartLocationRow() > bo.getEndLocationRow()) {
            log.error("起始终止排存在错误:" + bo.toString());
            return Result.err().msg("起始终止排存在错误");
        }
        if (bo.getStartLocationColumn() < 0L || bo.getEndLocationColumn() < 0L || bo.getStartLocationColumn() > bo.getEndLocationColumn()) {
            log.error("起始终止列存在错误:" + bo.toString());
            return Result.err().msg("起始终止列存在错误");
        }
        if (bo.getStartLayer() < 0L || bo.getEndLayer() < 0L || bo.getStartLayer() > bo.getEndLayer()) {
            log.error("起始终止层存在错误:" + bo.toString());
            return Result.err().msg("起始终止层存在错误");
        }
        BaseLocation temp = BeanUtil.toBean(bo, BaseLocation.class);
        // 获取起始终止编码之间的数据
        int rowLength = bo.getEndLocationRow().toString().length();
        int columnLength = bo.getEndLocationRow().toString().length();
        int layerLength = bo.getEndLayer().toString().length();
        // 获取区域编号
        BaseArea baseArea = iBaseAreaService.getById(bo.getAreaId());
        String s = baseArea.getAreaCode() + bo.getTunnel();

        for (Long a = bo.getStartLocationRow(); a <= bo.getEndLocationRow(); a++) {
            for (Long b = bo.getStartLocationColumn(); b <= bo.getEndLocationColumn(); b++) {
                for (Long c = bo.getStartLayer(); c <= bo.getEndLayer(); c++) {
                    BaseLocation baseLocation = new BaseLocation();
                    baseLocation.setAreaId(bo.getAreaId());
                    baseLocation.setTunnel(bo.getTunnel());
                    baseLocation.setLocationRow(a.toString());
                    baseLocation.setLocationColumn(b.toString());
                    baseLocation.setLayer(c.toString());
                    Result result = checkEntity(baseLocation);
                    if (!Result.isOk(result)) {
                        return Result.err().msg(result.getMsg());
                    }
                    // 创建对象
                    String code = s + "-"
                            + String.format("%0" + rowLength + "d", a)
                            + String.format("%0" + columnLength + "d", b)
                            + String.format("%0" + layerLength + "d", c);
                    baseLocation.setLocationCode(code);
                    baseLocation.setLocationName(code);
                    baseLocation.setType(bo.getType());
                    baseLocation.setLogicId(bo.getLogicId());
                    baseLocation.setStorageClassify(bo.getStorageClassify());
                    baseLocation.setLength(bo.getLength());
                    baseLocation.setWidth(bo.getWidth());
                    baseLocation.setHeight(bo.getHeight());
                    baseLocation.setVolume(bo.getLength().multiply(bo.getWidth()).multiply(bo.getHeight()));
                    baseLocation.setSkunum(bo.getSkunum());
                    baseLocation.setIsuse(bo.getIsuse());
                    baseLocation.setBranchId(SecurityUtils.getCurrentBranchId());
                    addList.add(baseLocation);
                }
            }
        }
        this.saveBatch(addList);
        return Result.ok();
    }

    /**
     * 保存或者修改货位（根据是否有id来判断新增或者修改）
     *
     * @param bo
     * @return
     */
    @Override
    public Result<Boolean> saveOrUpdateBaseLocation(BaseLocationSaveOrUpdateBo bo) {
        BaseLocation saveOrupDate = null;
        if (bo.getId() != null) {
            BaseLocation one = getById(bo.getId());
            if (one == null) {
                log.error("货位资料不存在:" + bo.toString());
                return Result.err().msg("货位资料不存在");
            }
        }
        saveOrupDate = BeanUtil.toBean(bo, BaseLocation.class);
        saveOrupDate.setBranchId(SecurityUtils.getCurrentBranchId());
        Result result = checkEntity(saveOrupDate);
        if (!Result.isOk(result)) {
            return Result.err().msg(result.getMsg());
        }
        this.saveOrUpdate(saveOrupDate);
        return Result.ok();
    }

    @Override
    public BaseLocationVo queryLocationById(Long targetLocationId) {
        return baseMapper.queryLocationById(targetLocationId);
    }

    @Override
    public BaseLocationVo queryLocationByCode(String locationCode) {
        return baseMapper.queryLocationByCode(locationCode, SecurityUtils.getCurrentBranchId());
    }

    @Override
    public BaseLocationVo queryLocationByName(String locationName) {
        return baseMapper.queryLocationByName(locationName, SecurityUtils.getCurrentBranchId());
    }


    /**
     * 校验数据 (相同仓下、相同区域、逻辑区域不允许重复)
     *
     * @param entity
     * @return
     */
    private Result<Boolean> checkEntity(BaseLocation entity) {
        Long id = entity.getId() != null ? entity.getId() : -1L;
        // 货位名称不能相同
        LambdaQueryWrapper<BaseLocation> wrapper = new LambdaQueryWrapper<BaseLocation>()
                .eq(BaseLocation::getLocationName, entity.getLocationCode())
                .eq(BaseLocation::getIsDel, IsDelEnum.NORMAL.getValue())
                .eq(BaseLocation::getBranchId, entity.getBranchId());
        BaseLocation one = getOne(wrapper);
        if (one != null && !id.equals(one.getId())) {
            log.error("存在货位编号相同的数据：" + entity.getLocationCode());
            return Result.err().msg("存在货位编号相同的数据");
        }

        return Result.ok();
    }


    @Override
    public Result<Boolean> switchStatus(Long id, String status) {
        BaseLocation location = new BaseLocation();
        location.setId(id).setIsuse(status);
        return this.updateById(location) ? Result.ok() : Result.err();
    }

    /**
     * 根据派生分配空货位
     *
     * @param deriveId
     * @param batch
     * @return
     */
    @Override
    public Result<BaseLocationVo> assignEmptyLocation(Long deriveId, String batch) {
        //获取派生对应的空货位
        BaseLocationQueryListBo bo = new BaseLocationQueryListBo();
        bo.setDeriveId(deriveId);
        bo.setLocationStatus("0");
        List<BaseLocationVo> baseLocationVos = this.baseMapper.queryBaseLocationListByDerive(bo);
        if (baseLocationVos.size() == 0) {
            return Result.err().msg("当前该派生对应的空货位可用");
        }
        //空货位所在巷道列表,同时过滤掉已有入库任务的巷道
        List<String> tunnelList = baseLocationVos.stream().map(e -> e.getTunnel()).distinct().filter(t -> TunnelTaskUtil.getInstance().getInboundTaskNum(t) == 0).collect(Collectors.toList());
        if (tunnelList.size() == 0) {
            return Result.err().msg("当前空货位所在巷道繁忙");
        }

        //从存在空货位的巷道里选择较优的巷道进行入库
        //首选选择任务数为空或者任务数最少的巷道
        //任务数相同时选取空货位最多的巷道
        List<String> tunnelResult = new ArrayList<>();
        Integer minTaskNum = 0;
        Integer maxEmptyLocationNum = 0;
        for (int i = 0; i < tunnelList.size(); i++) {
            String tunnel = tunnelList.get(i);
            Integer taskNum = TunnelTaskUtil.getInstance().getTotalTaskNum(tunnel);
            if (taskNum.equals(minTaskNum)) {
                int curEmptyNum = baseLocationVos.stream().filter(e -> tunnel.equals(e.getTunnel())).collect(Collectors.toList()).size();
                if (curEmptyNum == maxEmptyLocationNum) {
                    tunnelResult.add(tunnel);
                } else if (curEmptyNum > maxEmptyLocationNum) {
                    tunnelResult.clear();
                    tunnelResult.add(tunnel);
                }
            } else if (taskNum < minTaskNum) {
                minTaskNum = taskNum;
                tunnelResult.clear();
                tunnelResult.add(tunnel);
            }
        }

        //从选取的巷道中选择库位
        if (tunnelResult.size() > 0) {
            String tunnel = tunnelList.get(0);
            List<BaseLocationVo> resultLocationList = baseLocationVos.stream().filter(e -> tunnel.equals(e.getTunnel())).collect(Collectors.toList());
            BaseLocationVo locationVo = resultLocationList.get(0);
            //巷道中货位数大于1时，进行分配
            if (resultLocationList.size() > 1) {
                BaseLocationVo assginLocation = assginLocation(resultLocationList, deriveId, batch);
                if (assginLocation != null) {
                    locationVo = assginLocation;
                }
            }

            //确定分配该库位，并将库位状态改为已分配
            this.changeLocationStatus(locationVo.getId(), "4");
            locationVo.setLocationStatus("4");
            return Result.ok().data(locationVo);
        } else {
            return Result.err();
        }
    }

    //从选取的巷道中选择库位
    private BaseLocationVo assginLocation(List<BaseLocationVo> locationList, Long deriveId, String batch) {
        BaseLocationVo resultLocationVo = null;
        //根据拣货路径选择最近一个货位
        BaseLocationVo locationVo = locationList.get(0);
        //如果该货位为双深位，则直接选择该库位
        if ("1".equals(locationVo.getIsDeep())) {
            resultLocationVo = locationVo;
        } else {
            String locationRow = StringUtils.isNotEmpty(locationVo.getLocationRow()) ? locationVo.getLocationRow() : "";
            String layer = StringUtils.isNotEmpty(locationVo.getLayer()) ? locationVo.getLayer() : "";
            String locationColumn = StringUtils.isNotEmpty(locationVo.getLocationColumn()) ? locationVo.getLocationColumn() : "";
            List<BaseLocationVo> matchLocationList = locationList.stream().filter(e -> "1".equals(e.getIsDeep()) && locationRow.equals(e.getLocationRow()) && layer.equals(e.getLayer()) && locationColumn.equals(e.getLocationColumn())).collect(Collectors.toList());

            //如果该货位为单深位，则检查空货位是否存在对应双深位，如果存在，则选择对应双深位
            if (matchLocationList.size() > 0) {
                resultLocationVo = matchLocationList.get(0);
            } else {
                //否则，检查该单深位是否有对应双深位（有库存）如果有，同时库存为相同批次的则在该单深位分配货位
                Result<BaseLocationVo> deepLocationResult = this.getDeepLocation(locationVo);
                if (HttpStatus.SUCCESS == deepLocationResult.getCode()) {
                    BaseLocationVo deepLocation = deepLocationResult.getData();
                    Result<SysStockDetailVo> sysStockDetailVoResult = iSysStockDetailService.queryByLocation(deepLocation.getId());
                    if (HttpStatus.SUCCESS != sysStockDetailVoResult.getCode()) {
                        locationList.remove(0);
                        resultLocationVo = assginLocation(locationList, deriveId, batch);
                    }
                }
            }
        }
        return resultLocationVo;
    }


    /**
     * 检查当前货位是否有对应双深位
     *
     * @param locationVo 当前货位
     * @return
     */
    @Override
    public Result<BaseLocationVo> getDeepLocation(BaseLocationVo locationVo) {
        if ("0".equals(locationVo.getIsDeep())) {
            BaseLocationQueryListBo bo = new BaseLocationQueryListBo();
            bo.setAreaId(locationVo.getAreaId());
            bo.setTunnel(locationVo.getTunnel());
            bo.setLayer(locationVo.getLayer());
            bo.setLocationRow(locationVo.getLocationRow());
            bo.setLocationColumn(locationVo.getLocationColumn());
            bo.setIsDeep("1");
            List<BaseLocationVo> baseLocationVos = this.baseMapper.queryBaseLocationListByDerive(bo);
            if (baseLocationVos.size() > 0) {
                return Result.ok().data(baseLocationVos.get(0));
            }
        }
        return Result.err();
    }

    @Override
    public Result<Boolean> changeLocationStatus(Long id, String status) {
        if (id != null) {
            BaseLocation location = getById(id);
            if (location == null) {
                log.error("货位资料不存在:" + location.toString());
                return Result.err().msg("货位资料不存在");
            } else {
                //已分配
                if ((!"4".equals(status)) && "4".equals(location.getLocationStatus())) {
                    TunnelTaskUtil.getInstance().subInboundTaskNum(location.getTunnel());
                } else if ("4".equals(status) && "1".equals(location.getLocationStatus())) {
                    TunnelTaskUtil.getInstance().addInboundTaskNum(location.getTunnel());
                }
                location.setLocationStatus(status);
                return this.updateById(location) ? Result.ok() : Result.err();
            }
        } else {
            return Result.err().msg("货位ID为空");
        }
    }

    @Override
    public Result<ImportLocationVo> importLocation(List<BaseLocationExcelVo> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Result.err().msg("导入数据为空");
        }
        int failureNum = 0;
        List<Integer> indexList = new ArrayList<>();
        List<BaseLocation> addList = new ArrayList<>();
        List<BaseBranch> branchList = baseBranchService.list(new LambdaQueryWrapper<BaseBranch>().eq(BaseBranch::getIsDel, DeleteFlagEnum.NORMAL.getValue()));
        List<BaseArea> areaList = iBaseAreaService.list(new LambdaQueryWrapper<BaseArea>().eq(BaseArea::getIsDel, DeleteFlagEnum.NORMAL.getValue()));

        List<String> codes = new ArrayList<>();
        for (BaseLocationExcelVo excelVo : list) {
            try {
                BeanValidators.validateWithException(validator, excelVo);
                BaseLocation location = new BaseLocation();
                BeanMapperUtils.map(excelVo, location);
                if (codes.contains(excelVo.getLocationCode())) {
                    failureNum++;
                    continue;
                }

                BaseBranch branch = branchList.stream().filter(x -> x.getBranchCode().equals(excelVo.getBranchCode())).findFirst().orElse(null);
                if (branch == null) {
                    failureNum++;
                    continue;
                }

                BaseArea area = areaList.stream().filter(x -> x.getAreaCode().equals(excelVo.getAreaCode())).findFirst().orElse(null);
                if (area == null) {
                    failureNum++;
                    continue;
                }


                location.setBranchId(branch.getId())
                        .setLocationName(location.getLocationCode())
                        .setAreaId(area.getId())
                        .setIsuse(YesAndNoEnum.YES.getValue());
                location.setIsDel(DeleteFlagEnum.NORMAL.getValue());
                Result<Boolean> booleanResult = checkEntity(location);
                if (!Result.isOk(booleanResult)) {
                    failureNum++;
                    continue;
                }
                //防止重复
                codes.add(location.getLocationCode());

                addList.add(location);
                indexList.add(list.indexOf(excelVo) + 1);
            } catch (Exception e) {
                log.error("导入订单异常 = {} ; excelVo = {}", e, excelVo);
                failureNum++;
            }
        }
        this.saveBatch(addList);
        ImportLocationVo importLocationVo = new ImportLocationVo();
        importLocationVo.setTotalNumber(list.size());
        importLocationVo.setSuccessNumber(list.size() - failureNum);
        importLocationVo.setFailureNumber(failureNum);

        importLocationVo.setIndexList(indexList);
        return Result.ok().data(importLocationVo);
    }

    @Override
    public BaseLocation getByLocationCode(String locationCode) {
        return getOne(new LambdaQueryWrapper<BaseLocation>().eq(BaseLocation::getLocationCode, locationCode));
    }

    @Override
    public List<BaseLocationMapListVo> getBaseLocationForMap(BaseLocationQueryPageBo bo) {
        return this.baseMapper.getBaseLocationForMap(bo);
    }

    public List<BaseLocationVo> getTunnel(String goodsId) {
        return this.baseMapper.gettunnel(goodsId);
    }



}
