package com.shkj.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shkj.common.constant.RedisConstant;
import com.shkj.common.core.domain.Result;
import com.shkj.common.utils.DateUtils;
import com.shkj.system.service.ISysParameterService;
import com.shkj.wms.bo.*;
import com.shkj.wms.constants.ParameterConstants;
import com.shkj.wms.domain.*;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.mapper.*;
import com.shkj.wms.service.*;
import com.shkj.wms.utils.TunnelTaskUtil;
import com.shkj.wms.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务管理Service业务层处理
 *
 * @author zjx
 * @date 2023-04-07
 */
@Slf4j
@Service
public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, BusinDataTask> implements IBusinDataTaskService {
    @Autowired
    private BusinDataTaskMapper businDataTaskMapper;

    @Autowired
    private BusinDataTaskDetailMapper businDataTaskDetailMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Resource
    BaseLocationPlcMapper baseLocationPlcMapper;

    @Resource
    ISysParameterService sysParameterService;

    @Resource
    BaseLocationServiceImpl baseLocationService;

    @Resource
    IBaseDeriveService iBaseDeriveService;

    @Resource
    IBaseGoodsDataService iBaseGoodsDataService;

    @Resource
    IBaseBarcodesOutService iBaseBarcodesOutService;

    @Resource
    IBusinDataTaskGoodsService iBusinDataTaskGoodsService;

    @Resource
    IBusinDataTaskService iBusinDataTaskService;

    @Resource
    IPutInOutStorageService iPutInOutStorageService;

    @Resource
    BaseGoodsDataMapper baseGoodsDataMapper;

    @Resource
    SysStockDetailMapper sysStockDetailMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> insertBusinTask(BaseContainerCallBo callBo) {
        //验证点位信息已经呼叫，尚未执行给与提示信息
        BasePointDeviceQueryBo bo = new BasePointDeviceQueryBo();
        bo.setPointNo(callBo.getPointNo());
        BasePointDeviceVo basePointDeviceVo = baseLocationPlcMapper.selectBasePointByGroupno(bo).get(0);
        if (basePointDeviceVo == null) {
            return Result.err().msg("入库点位信息不存在");
        }

        String taskCode = UUID.randomUUID().toString();
        BusinTaskAddBo businTaskAddBo = new BusinTaskAddBo();
        businTaskAddBo.setTaskType(TaskTypeEnum.call_container.getValue());
        businTaskAddBo.setTaskCode(taskCode);
        businTaskAddBo.setTaskStatus(TaskStatusEnum.wait_put.getValue());
        businTaskAddBo.setIsDown(basePointDeviceVo.getIsDown());

        BusinTaskDetailAddBo dtls = new BusinTaskDetailAddBo();
        dtls.setTaskCode(taskCode);
        dtls.setEndLocation(callBo.getPointNo());
        dtls.setUpdateTime(DateUtils.getNowDate());

        this.baseMapper.insert(BeanUtil.toBean(businTaskAddBo, BusinDataTask.class));

        businDataTaskDetailMapper.insert(BeanUtil.toBean(dtls, BusinDataTaskDetail.class));
        return Result.ok();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> insertBusinTask(BusinDataTask businDataTask) {
        String taskCode = UUID.randomUUID().toString();

        businDataTask.setTaskType(TaskTypeEnum.call_container.getValue());
        businDataTask.setTaskCode(taskCode);
        businDataTask.setTaskStatus(TaskStatusEnum.wait_put.getValue());
        this.save(businDataTask);
        return Result.ok();
    }

    @Override
    public Result<Boolean> insertBusinTask(List<BaseBarcodesOutAddBo> bs) {
        List<BusinDataTask> taskList = new ArrayList<>();
        List<BusinDataTaskGoods> taskGoodsList = new ArrayList<>();
        for (BaseBarcodesOutAddBo baseBarcodesOut : bs) {
            //回填出库队列的状态
            baseBarcodesOut.setOutStatus("1");
            //根据出库中的车型代码，派生查找派生表中的保险杠信息
            BaseDeriveQueryBo baseDeriveQueryBo = new BaseDeriveQueryBo();
            baseDeriveQueryBo.setDerive(baseBarcodesOut.getDerive());
            baseDeriveQueryBo.setVehicheCode(baseBarcodesOut.getVehicleCode());

            BaseDerive baseDerive = iBaseDeriveService.getBaseDeriveBybarcodes(baseDeriveQueryBo);

            //获取出库组装接驳点位
            String outboundPoint = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.outbound_point);
            //生成作业任务
            BusinDataTask task = new BusinDataTask();
            String taskCode = "T"+DateUtils.dateTimeNow();
            task.setTaskCode(taskCode);
            task.setTaskType(TaskTypeEnum.normal_out.getValue());
            task.setBatch(DateUtils.dateTime(baseBarcodesOut.getTraverseDate()));
            task.setPriority("2");
            task.setIsTop("0");
            task.setIsUrgent(baseBarcodesOut.getIsUrgent());
            task.setCreateTime(DateUtils.getNowDate());
            task.setTraverseDate(DateUtils.parseDate(baseBarcodesOut.getTraverseDate()));
            task.setTaskPath(outboundPoint);
            taskList.add(task);

            iBaseBarcodesOutService.save(baseBarcodesOut);

            businDataTaskMapper.insertBusinDataTask(task);
            Long taskId = task.getId();

            //根据派生信息查找物料信息，需要前杠和后杠
            BusinDataTaskGoods taskGoods = new BusinDataTaskGoods();
            List<BaseGoodsData> goodsDataList = iBaseGoodsDataService.getBaseGoodDataInByDerice(baseDerive);
            for (BaseGoodsData baseGoodsData : goodsDataList) {
                taskGoods.setGoodsNo(baseGoodsData.getGoodsNo());
                taskGoods.setTaskCode(taskId);
                taskGoodsList.add(taskGoods);
            }
            iBusinDataTaskGoodsService.saveBatch(taskGoodsList);
        }

        return Result.ok();
    }


    @Override
    public Result<BasePointDeviceVo> getManualWarehousingPoint() {
        BasePointDeviceQueryBo bo = new BasePointDeviceQueryBo();
        //获取人工入库点位分组
        String tepairPoint = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.warehousing_group);

        bo.setGroupNo("10");
        List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(bo);
        return Result.ok().data(basePointDeviceVos);
    }

    @Override
    public Result<Boolean> insertBusinTask(BaseBarcodesIn baseBarcodesIn, String taskCode) {
        BusinTaskAddBo businTaskAddBo = new BusinTaskAddBo();
        businTaskAddBo.setTaskCode(taskCode);
        businTaskAddBo.setQrCode(baseBarcodesIn.getQrCode());
        businTaskAddBo.setGoodsNo(baseBarcodesIn.getGoodsNo());
        businTaskAddBo.setTaskStatus("0");
        businTaskAddBo.setBatch(DateUtils.dateTime());
        businTaskAddBo.setIsUrgent("0");
        businTaskAddBo.setIsTop("0");
        businTaskAddBo.setPriority(999);
        businTaskAddBo.setTaskStarttime(new Date());

        this.insertByAddBo(businTaskAddBo);

        return Result.ok();
    }


    @Override
    public Result<Boolean> insertByAddBo(BusinTaskAddBo bo) {
        LambdaQueryWrapper<BusinDataTask> wrapper = new LambdaQueryWrapper<BusinDataTask>().eq(BusinDataTask::getTransId, bo.getTransId()).last("limit 1");
        BusinDataTask businDataTask = getOne(wrapper);
        if (businDataTask != null) {
            return Result.err().msg("条码信息任务已创建");
        }
        BusinDataTask businDataTaskAdd = BeanUtil.toBean(bo, BusinDataTask.class);
        this.save(businDataTaskAdd);
        return Result.ok();
    }

    @Override
    public Result<Boolean> getReplenishmentAndOutbound(BusinOutboundQueryBo bo) {
        List<BasinBarcodeInAddBo> barcodesList = bo.getBarcodesList();
        for (BasinBarcodeInAddBo barcode : barcodesList) {
            //根据车型和颜色查询出整套保险杠 A B ，目前知道是A，需要查询B在库存的情况
            //获取车型+颜色
            BaseBarcodesInQueryBo queryBo = new BaseBarcodesInQueryBo();
            queryBo.setVehicheModel(barcode.getVehicheModel());
            queryBo.setColor(barcode.getColor());
            queryBo.setIsSplit(barcode.getIsSplit());
            queryBo.setLocationCode(barcode.getLocationCode());
            queryBo.setIsPunching(barcode.getIsPunching());
            queryBo.setLocation(barcode.getLocation());
            queryBo.setOrientation(barcode.getOrientation());
            //根据物料查询需要成套的保险杠信息
            List<BaseGoodsData> goodsDataList = baseGoodsDataMapper.getBaseGoodDataNotBarcode(queryBo);
            for (BaseGoodsData baseGoodsData : goodsDataList) {
                //查询库存在库情况
                List<SysStockDetailVo> detailVos = sysStockDetailMapper.getInventoryInStockByGoods(baseGoodsData.getGoodsNo());
                //生成待执行任务
                this.insertBusinDataTask(detailVos);

            }
        }
        return Result.ok();
    }

    public  Boolean insertBusinDataTask(List<SysStockDetailVo> detailVos){

        List<BusinDataTask> taskList = new ArrayList<>();
        List<BusinDataTaskGoods> taskGoodsList = new ArrayList<>();
        for (SysStockDetailVo detailVo : detailVos) {
            //生成作业任务
            BusinDataTask task = new BusinDataTask();
            String taskCode = "T"+DateUtils.dateTimeNow();
            task.setTaskCode(taskCode);
            task.setTaskType(TaskTypeEnum.replenish.getValue());
            task.setPriority("2");
            task.setIsTop("0");
            task.setIsUrgent("0");
            task.setCreateTime(DateUtils.getNowDate());
//            task.setFromRow(detailVo.getLocationRow());
//            task.setFromColumn(detailVo.getLocationColumn());
//            task.setFromLayer(detailVo.getLayer());
            businDataTaskMapper.insertBusinDataTask(task);
            Long taskId = task.getId();
            BusinDataTaskGoods taskGoods = new BusinDataTaskGoods();
            taskGoods.setGoodsNo(detailVo.getMoldNo());
            taskGoods.setTaskCode(taskId);
            taskGoods.setBranchId(detailVo.getBranchId());
            return  iBusinDataTaskGoodsService.save(taskGoods)?true: false;
        }
        return false;
    }
    @Override
    public Long insertBusinDataTask(BusinDataTask businDataTask) {
        return businDataTaskMapper.insertBusinDataTask(businDataTask);
    }

    @Override
    public BusinDataTask getBusinDataTaskByQrCode(String qrCode) {
        //获取条码信息
        BusinDataTask businDataTask = (BusinDataTask) redisTemplate.opsForValue().get(RedisConstant.redisTaskData + qrCode);
        if (businDataTask == null) {
            businDataTask = businDataTaskMapper.selectBusinDataTaskByQrcode(qrCode);
        }
        return businDataTask;
    }

    @Override
    public BusinDataTask getBusinDataTaskByTraverseDate(Date traverseDate) {
        BusinDataTask businDataTask = businDataTaskMapper.getBusinDataTaskByTraverseDate(traverseDate);
        return businDataTask;
    }

    @Override
    public List<BusinDataTaskVo> selectBusinDataTask(BusinTaskQueryBo bo) {
        return businDataTaskMapper.selectBusinDataTask(bo);
    }

    /**
     * 返回巷道，堆垛机编号 货位信息
     *
     * @return*/

    @Override
    public List<BusinDataTask> outboundInfo(List<BusinDataTaskGoodsVo> goods){
        List<BusinDataTask> taskList = new ArrayList<>();
        for (BusinDataTaskGoodsVo good : goods) {
            //根据物料查询所在仓库
            List<BaseLocationVo> tunnelVo = baseLocationService.getTunnel(good.getGoodsNo());
            List<String> tunnelall = tunnelVo.stream().map(e -> e.getTunnel()).collect(Collectors.toList());
            //拿到任务数最少的巷道
            String tunnelone=this.quickSort(tunnelall);
            List<BaseLocationVo> tunnelLocation = tunnelVo.stream().filter(e -> e.getTunnel().equals(tunnelone)).collect(Collectors.toList());
            //根据巷道分配货位
            BaseLocationVo baseLocationVo = tunnelLocation.get(0);

            //修改出库表状态为进行中并添加任务
            BusinDataTask businDataTask = new BusinDataTask();
            //回填任务相关数据
            businDataTask.setFromColumn(String.valueOf(baseLocationVo.getLocationColumn()));
            businDataTask.setFromLayer(baseLocationVo.getLocationColumn());
            businDataTask.setFromRow(baseLocationVo.getLocationRow());
            businDataTask.setDevId(baseLocationVo.getDevId());
            //添加巷道任务数和总任务数
            TunnelTaskUtil.getInstance().addOutboundTaskNum(baseLocationVo.getTunnel());
            TunnelTaskUtil.getInstance().getOutboundTaskNum(baseLocationVo.getTunnel());
            iBusinDataTaskService.save(businDataTask);

            //生成出库明细
            BusinTaskExeBo exeBo = new BusinTaskExeBo();
            exeBo.setTaskCode(businDataTask.getId());
            exeBo.setBusinDataTaskGoodsVo(goods);
            exeBo.setBaseLocationVo(baseLocationVo);
            exeBo.setTransNo("1");
            exeBo.setTransQual("1");

            ////生成出库单
            Result<String> billResult = iPutInOutStorageService.exeTaskPutinStorage(exeBo);
            businDataTask.setTransId(billResult.getData());
            taskList.add(businDataTask);
        }
        return  taskList;
    }


    /**
     * 返回任务数最少的巷道号
     * @param tunnelall
     * @return
     */

    public String quickSort(List<String> tunnelall){
        String tunnel= "";
        Map<String,Integer> tunnelmap =new HashMap<>();

        tunnelall.stream().forEach(
                e->{
                    tunnelmap.put(e, TunnelTaskUtil.getInstance().getInboundTaskNum(e));
                }
        );
        List<Integer> collect = tunnelmap.values().stream().sorted().collect(Collectors.toList());
        for (String key:
                tunnelmap.keySet()) {
            if (tunnelmap.get(key).equals(collect.get(0))){
                tunnel=key;
            }

        }
        return tunnel;
    }


}
