package com.zbf.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbf.common.annotation.DataScope;
import com.zbf.common.annotation.Log;
import com.zbf.common.core.domain.model.LoginUser;
import com.zbf.common.enums.BusinessType;
import com.zbf.common.utils.DateUtils;
import com.zbf.common.utils.OrderCodeFactory;
import com.zbf.common.utils.SecurityUtils;
import com.zbf.system.domain.*;
import com.zbf.system.mapper.*;
import com.zbf.system.service.ITBaseStorageService;
import com.zbf.system.service.ITCallNoticeOrderService;
import com.zbf.system.service.ITCallNoticeService;
import com.zbf.system.service.ITCkPickingwavegoodsService;
import com.zbf.system.utils.DeviceInfo;
import com.zbf.system.utils.HttpUtils;
import com.zbf.system.utils.SignTool;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 出库任务Service业务层处理
 *
 * @author tony
 * @date 2024-06-14
 */
@Service
public class TCkPickingwavegoodsServiceImpl extends ServiceImpl<TCkPickingwavegoodsMapper, TCkPickingwavegoods> implements ITCkPickingwavegoodsService //修改
{

    private static final Logger logger = LoggerFactory.getLogger(TCkPickingwavegoodsServiceImpl.class);

    @Autowired
    private TOngoodsshelfServiceImpl tOngoodsshelfService;
    @Autowired
    private TOngoodsshelfMapper tOngoodsshelfMapper;
    @Resource
    private TCkPickingwavegoodsMapper tCkPickingwavegoodsMapper;
    @Autowired
    private TCkPickingwavegoodsBakServiceImpl tCkPickingwavegoodsBakService;
    @Resource
    private TMiStockMapper tMiStockMapper;
    @Resource
    private TBaseStorageAreaLocationMapper tBaseStorageAreaLocationMapper;
    @Resource
    private TCkOrderdetailMapper tCkOrderdetailMapper;
    @Resource
    private TCkPickingwavegoodsServiceImpl tCkPickingwavegoodsService;
    @Autowired
    private TCkOrdersMapper tCkOrdersMapper;
    @Autowired
    private TckOrdersBakServiceImpl tckOrdersBakService;

    @Autowired
    private ITBaseStorageService baseStorageService;
    @Autowired
    private TCkOrdersServiceImpl tCkOrdersService;

	@Autowired
    private ITCallNoticeService tNoticeService;

    @Autowired
    private ITCallNoticeOrderService tNoticeOrderService;

    @Autowired
    private DeviceLogMapper deviceLogMapper;

    @Value("deviceIp")
    private String deviceIp;
    @Autowired
    private TBasePalletMapper basePalletMapper;

    /**
     * 查询出库任务
     *
     * @param id 出库任务主键
     * @return 出库任务
     */
    @Override
    public TCkPickingwavegoods selectTCkPickingwavegoodsById(String id) {
        return tCkPickingwavegoodsMapper.selectTCkPickingwavegoodsById(id);
    }
    private List<TBaseStorage> getStorageList(Long deptId){
        TBaseStorage baseStorage = new TBaseStorage();
        baseStorage.setDeptId(deptId);
        return baseStorageService.selectTBaseStorageList(baseStorage);

    }
    /**
     * 查询出库任务列表
     *
     * @param tCkPickingwavegoods 出库任务
     * @return 出库任务
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<TCkPickingwavegoods> selectTCkPickingwavegoodsList(TCkPickingwavegoods tCkPickingwavegoods) {
        /*List<TBaseStorage> storageList = getStorageList(tCkPickingwavegoods.getDeptId());
        if(storageList.size() > 0){
            tCkPickingwavegoods.setStorageList(storageList.stream().map(TBaseStorage::getStorageId).collect(Collectors.toList()));
        }*/
        return tCkPickingwavegoodsMapper.selectTCkPickingwavegoodsList(tCkPickingwavegoods);
    }

    /**
     * 新增出库任务
     *
     * @param tCkPickingwavegoods 出库任务
     * @return 结果
     */
    @Override
    public int insertTCkPickingwavegoods(TCkPickingwavegoods tCkPickingwavegoods) {
        tCkPickingwavegoods.setCreateTime(DateUtils.getNowDate());
        tCkPickingwavegoods.setUpdateTime(new Date());
        if (StringUtils.isEmpty(tCkPickingwavegoods.getId())) {
            tCkPickingwavegoods.setId(OrderCodeFactory.getOrderCode("CK", ""));
        }
        if (StringUtils.isBlank(tCkPickingwavegoods.getWareDate())) {
            tCkPickingwavegoods.setWareDate(DateUtils.getTime());
        }
        return tCkPickingwavegoodsMapper.insertTCkPickingwavegoods(tCkPickingwavegoods);
    }

    /**
     * 修改出库任务
     *
     * @param tCkPickingwavegoods 出库任务
     * @return 结果
     */
    @Override
    public int updateTCkPickingwavegoods(TCkPickingwavegoods tCkPickingwavegoods) {
        tCkPickingwavegoods.setUpdateTime(DateUtils.getNowDate());
        return tCkPickingwavegoodsMapper.updateTCkPickingwavegoods(tCkPickingwavegoods);
    }

    /**
     * 批量删除出库任务
     *
     * @param ids 需要删除的出库任务主键
     * @return 结果
     */
    @Override
    public int deleteTCkPickingwavegoodsByIds(String[] ids) {
        logger.info("手动删除出库任务：{}", ids);

        //删除出库的所有记录
        for (String id : ids) {
            TCkPickingwavegoods tCkPickingwavegoods = selectTCkPickingwavegoodsById(id);
            TCkPickingwavegoods tCkPickingwavegoods1 = new TCkPickingwavegoods();
            tCkPickingwavegoods1.setCtl(tCkPickingwavegoods.getCtl());
            logger.info("删除全部数据，托盘号为：{}", tCkPickingwavegoods.getCtl());
            tCkPickingwavegoodsMapper.deleteGoods(tCkPickingwavegoods1);

            //释放库存状态
            TMiStock tMiStock = new TMiStock();
            tMiStock.setStatus("0");
            tMiStock.setCtl(tCkPickingwavegoods.getCtl());
            logger.info("更新库存库位状态：{}", tCkPickingwavegoods.getCtl());
            tMiStockMapper.updateSts(tMiStock);
        }
        //return tCkPickingwavegoodsMapper.deleteTCkPickingwavegoodsByPickingids(ids);
        return 1;
    }


    /**
     * 删除出库任务信息
     *
     * @param id 出库任务主键
     * @return 结果
     */
    @Override
    public int deleteTCkPickingwavegoodsById(String id) {
        return tCkPickingwavegoodsMapper.deleteTCkPickingwavegoodsById(id);
    }


    /**
     * 批量禁用
     *
     * @param ids 出库任务主键
     * @return 结果
     */
    @Override
    public int disabledTCkPickingwavegoodsByIds(String[] ids) {
        return tCkPickingwavegoodsMapper.disabledTCkPickingwavegoodsByIds(ids);
    }

    /**
     * 批量启用
     *
     * @param ids 出库任务主键
     * @return 结果
     */
    @Override
    public int enableTCkPickingwavegoodsByIds(String[] ids) {
        return tCkPickingwavegoodsMapper.enableTCkPickingwavegoodsByIds(ids);
    }

    /**
     * 修改状态
     *
     * @param tCkPickingwavegoods 工序管理主键
     * @return 结果
     */
    @Override
    public int updateStatus(TCkPickingwavegoods tCkPickingwavegoods) {
        return tCkPickingwavegoodsMapper.updateTCkPickingwavegoods(tCkPickingwavegoods);
    }

    @Override
    public List<Map<String, Object>> selectMaps(QueryWrapper<TCkPickingwavegoods> queryWrapper) {
        return tCkPickingwavegoodsMapper.selectMaps(queryWrapper);
    }

    /**
     * 出库任务
     *
     * @param s
     * @param statuses
     * @return
     */
    @Override
    public Map<String, Object> createTaskData(String s, List<Integer> statuses) {
        QueryWrapper<TCkPickingwavegoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("status", "SUM(goods_num) as count")
                .in("status", statuses)
                .groupBy("status");
        List<Map<String, Object>> maps = this.selectMaps(queryWrapper);
        Map<String, Object> taskData = new HashMap<>();
        taskData.put("product", s);
        List<String> dimensions = Arrays.asList("product", "待执行", "执行中", "完成");

        // 封装
        for (Map<String, Object> map : maps) {
            String status = map.get("status").toString();
            BigDecimal count = (BigDecimal) map.get("count");
            int totalCount = count.intValue(); // 获取BigDecimal的整数部分
            taskData.put(dimensions.get(Integer.parseInt(status) + 1), totalCount);
        }
        return taskData;
    }

    @Override
    public List<TCkPickingwavegoods> list(LambdaQueryWrapper<TCkPickingwavegoods> tCkPickingwavegoodsLambdaQueryWrapper) {
        return tCkPickingwavegoodsMapper.selectList(tCkPickingwavegoodsLambdaQueryWrapper);
    }


    @Override
    public List<TCkPickingwavegoods> selectJxList(TCkPickingwavegoods tCkPickingwavegoods) {
        return tCkPickingwavegoodsMapper.selectJxList(tCkPickingwavegoods);
    }

    @Override
    public int updateStatusByPickingids(List<String> ids, TCkPickingwavegoods tCkPickingwavegoods) {
        Map<String, Object> params = new HashMap<>();
        params.put("list", ids);
        params.put("status", tCkPickingwavegoods.getStatus());
        return tCkPickingwavegoodsMapper.updateStatusByLotIds(params);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTCkPickingwavegoodsList(List<TCkOrderdetail> tCkOrderdetailList) {
        if (tCkOrderdetailList == null || tCkOrderdetailList.size() == 0) {
            logger.error("出库请求列表为空异常");
            throw new RuntimeException("出库请求列表为空异常");
        }
//        TCkPickingwavegoods tCkPickingwavegoods1 = new TCkPickingwavegoods();
//        tCkPickingwavegoods1.setCkType("3");
//        List<TCkPickingwavegoods> ckTypeList = tCkPickingwavegoodsService.selectList(tCkPickingwavegoods1);
//        if(ckTypeList.size() > 0){
//            logger.error("有移库任务，请稍后再试");
//            throw new RuntimeException("有移库任务，产生出库任务失败！");
//        }
        logger.info("出库请求解析开始：{}", tCkOrderdetailList);
        //value: 以托盘号为key，该托盘出库该物料的出库数量为value的map
        Map<String, Map<String, BigDecimal>> goodsMap = new HashMap<String, Map<String, BigDecimal>>();
        for (TCkOrderdetail orderdetail : tCkOrderdetailList) {
            if ("2".equals(orderdetail.getConfirmStatus())) {
                logger.info("已出库完成的忽略：{}", orderdetail.getGoodsId());
                continue;
            }
            //存储每个托盘的需要出的数量
            Map<String, BigDecimal> ctlMap = new HashMap<>();
            //根据物料ID查询库存，按照先进先出的原则，按入库时间倒叙查询
            TMiStock tMiStock = new TMiStock();
            tMiStock.setGoodsId(orderdetail.getGoodsId());
            tMiStock.setSalesOrderNumber(orderdetail.getBusinessId());
            //如果设置了某个堆垛机，则需要新增条件
//            if (StringUtils.isNotBlank(orderdetail.getXqType())) {
//                tMiStock.setDecid(orderdetail.getXqType());
//            }
            List<TMiStock> tMiStocks = tMiStockMapper.selectList(new QueryWrapper<>(tMiStock));

            if (tMiStocks.size() == 0) {
                logger.warn("未找到该物料库存：{}", orderdetail.getGoodsId());
                throw new RuntimeException("未找到该物料库存：" + orderdetail.getGoodsId());
            }
            //本次出库数量
            BigDecimal goodsNum = orderdetail.getGoodsNum();

            BigDecimal total = BigDecimal.ZERO;
            for (TMiStock tMiStock1 : tMiStocks) {
                total = total.add(tMiStock1.getShelvesNum());
                if (orderdetail.getPickNum() == null) {
                    orderdetail.setPickNum(BigDecimal.ZERO);
                }
                if (goodsNum.compareTo(total) == 0) {
                    ctlMap.put(tMiStock1.getCtl(), tMiStock1.getShelvesNum());
                    orderdetail.setPickNum(orderdetail.getPickNum().add(tMiStock1.getShelvesNum()));
                    break;
                } else if (goodsNum.compareTo(total) > 0) {
                    ctlMap.put(tMiStock1.getCtl(), tMiStock1.getShelvesNum());
                    orderdetail.setPickNum(orderdetail.getPickNum().add(tMiStock1.getShelvesNum()));
                } else {
                    //小于0
                    BigDecimal subtract = total.subtract(goodsNum);
                    BigDecimal subtract1 = tMiStock1.getShelvesNum().subtract(subtract);
                    ctlMap.put(tMiStock1.getCtl(), subtract1);
                    orderdetail.setPickNum(orderdetail.getPickNum().add(subtract1));
                    break;
                }
            }
            //存储在大的map中
            goodsMap.put(orderdetail.getGoodsId(), ctlMap);
            logger.info("更新累计出库数量：{}", orderdetail);
            orderdetail.setStatus("1");
            tCkOrderdetailMapper.updateTCkOrderdetail(orderdetail);
        }

        //创建出库任务
        /**
         * 假如 物料A 需要出库的托盘为1 ，3 ，8
         * 物料B 需要出库的托盘为1，5
         * 则本次出库的总的任务为4个，1，3，5，8
         * 根据这个逻辑进行开发
         */

        //lambda表达式遍历
        //蒋map进行转换，转换为以托盘为大key，以物料和数量为小map的map
        Map<String, Map<String, BigDecimal>> ctlGoodsMap = new HashMap<>();
        goodsMap.forEach((goodsId, ctlMap) -> {
            ctlMap.forEach((ctl, shelvNum) -> {
                AtomicBoolean isExist = new AtomicBoolean(false);
                ctlGoodsMap.forEach((key, value) -> {
                    if (ctl.equals(key)) {
                        isExist.set(true);
                        value.put(goodsId, shelvNum);
                    }
                });

                if (!isExist.get()) {
                    Map<String, BigDecimal> map = new HashMap<>();
                    map.put(goodsId, shelvNum);
                    ctlGoodsMap.put(ctl, map);
                }

            });
        });

        logger.info("生成以托盘号为主键的map：{}", ctlGoodsMap);

        //根据每个托盘创建出库任务
        //1. 判断出库任务是否已产生该托盘的任务
        //获取订单号
        String orderId = tCkOrderdetailList.get(0).getOrderId();
        ctlGoodsMap.forEach((key, value) -> {
            TCkPickingwavegoods tCkPickingwavegoods = new TCkPickingwavegoods();
            tCkPickingwavegoods.setCtl(key);
            //判断该托盘是否产生出库任务
            List<TCkPickingwavegoods> tCkPickingwavegoodsList = tCkPickingwavegoodsMapper.selectList(new QueryWrapper<>(tCkPickingwavegoods));
            if (tCkPickingwavegoodsList.size() > 0) {
                logger.error("该托盘已产生出库任务：{}", key);
                throw new RuntimeException("该托盘已产生出库任务：" + key);
            }

            //出库
            setCk(key, value, orderId);

        });

        return 1;
    }

    /**
     * 首页出库统计
     *
     * @return
     */
    @Override
    @DataScope(deptAlias = "d")
    public Integer homePickingwavegoodsCount(TCkPickingwavegoods pickingwavegoods) {

        // 出库统计
        List<Map<String, Integer>> countOut = tCkPickingwavegoodsMapper.counts(pickingwavegoods);

        return countOut.size();
    }
    /**
     * 首页出库任务未审核完成统计
     *
     * @return
     */
    @Override
    @DataScope(deptAlias = "d")
    public Integer homeTCkOrdersCount(TCkOrders orders) {
        List<TCkOrders> list = tCkOrdersMapper.selectTCkOrdersList(orders);
        Integer collect = Math.toIntExact(list.stream().filter(tCkOrders -> tCkOrders.getIsAudit().equals("0")).count());
        return collect;
    }

    /**
     * 首页入库统计
     *
     * @return
     */
    @Override
    @DataScope(deptAlias = "d")
    public Integer homeOngoodsshelfCount(TOngoodsshelf tOngoodsshelf) {
        // 入库统计
        List<Map<String, Integer>> countIn = tOngoodsshelfMapper.counts(tOngoodsshelf);
        return countIn.size();
    }

    private void setCk(String ctl, Map<String, BigDecimal> map, String orderId) {
        TMiStock tMiStock = new TMiStock();
        tMiStock.setCtl(ctl);
        //该托盘的所有物料
        List<TMiStock> tMiStocks = tMiStockMapper.selectTMiStockList(tMiStock);
        logger.info("该库位库存列表为：{}", tMiStocks);
        //判断是否需要移库
        String locId = tMiStocks.get(0).getLocationId();
        String decid = tMiStocks.get(0).getDecid();
        String sts = tMiStocks.get(0).getStatus();
        if ("1".equals(sts)) {
            logger.error("该库存为锁定状态，请确认！");
            throw new RuntimeException("该库存为锁定状态，请确认！");
        }
        if (StringUtils.isBlank(locId)) {
            throw new RuntimeException("获取库位异常");
        }
        boolean isTransfer = false;
        if (locId.endsWith("2")) {
            //判断01是否有货
            String locationId = locId.substring(0, locId.length() - 1) + "1";
            TCkPickingwavegoods tCkPickingwavegoods4 = new TCkPickingwavegoods();
            tCkPickingwavegoods4.setLocationId(locationId);
            List<TCkPickingwavegoods> ckTypeList4 = tCkPickingwavegoodsMapper.selectList(new QueryWrapper<>(tCkPickingwavegoods4));
            if (ckTypeList4.size() > 0) {
                logger.error(locationId + "有出库任务，请稍后再试");
                throw new RuntimeException(locationId + "有出库任务，请稍后再试！");
            }
            //先判断是否有移库任务
            TCkPickingwavegoods tCkPickingwavegoods1 = new TCkPickingwavegoods();
            tCkPickingwavegoods1.setCkType("3");
            tCkPickingwavegoods1.setToLoc(locationId);
            List<TCkPickingwavegoods> ckTypeList = tCkPickingwavegoodsMapper.selectList(new QueryWrapper<>(tCkPickingwavegoods1));
            if (ckTypeList.size() > 0) {
                logger.error(locationId + "有移库任务，请稍后再试");
                throw new RuntimeException(locationId + "有移库任务，请稍后再试！");
            }
            TOngoodsshelf tOngoodsshelf = new TOngoodsshelf();
            tOngoodsshelf.setLocationId(locationId);
            List<TOngoodsshelf> tOngoodsshelves = tOngoodsshelfService.selectTOngoodsshelfList(tOngoodsshelf);
            if (tOngoodsshelves.size() > 0) {
                logger.error(locationId + "有入库任务，请稍后再试");
                throw new RuntimeException(locationId + "有入库任务，请稍后再试！");
            }
            TBaseStorageAreaLocation areaLocation = new TBaseStorageAreaLocation();
            areaLocation.setStatus("1");
            areaLocation.setLocationId(locationId);
            String transferCtl = StringUtils.EMPTY;
            String transferDecid = StringUtils.EMPTY;
            List<TBaseStorageAreaLocation> tBaseStorageAreaLocations = tBaseStorageAreaLocationMapper.selectTBaseStorageAreaLocationList(areaLocation);
            if (tBaseStorageAreaLocations.size() > 0) {
                TMiStock tMiStock1 = new TMiStock();
                tMiStock1.setLocationId(locationId);
                List<TMiStock> tMiStocks1 = tMiStockMapper.selectTMiStockList(tMiStock1);
                if (tMiStocks1.size() > 0) {
                    transferCtl = tMiStocks1.get(0).getCtl();
                    transferDecid = tMiStocks1.get(0).getDecid();
                    isTransfer = true;
                }
            } else {
                TMiStock tMiStock1 = new TMiStock();
                tMiStock1.setLocationId(locationId);
                List<TMiStock> tMiStocks1 = tMiStockMapper.selectTMiStockList(tMiStock1);
                if (tMiStocks1.size() > 0) {
                    transferCtl = tMiStocks1.get(0).getCtl();
                    transferDecid = tMiStocks1.get(0).getDecid();
                    String sts1 = tMiStocks1.get(0).getStatus();
                    if ("1".equals(sts1)) {
                        logger.error(locId + "：产生出库任务失败，" + locId + "：该库位产生出库任务失败");
                        throw new RuntimeException(locId + "：产生出库任务失败，" + locId + "该库位产生出库任务失败");
                    }
                    isTransfer = true;
                }
            }
            //移库
            if (isTransfer) {
//                    查询空闲库位
                List<TBaseStorageAreaLocation> tBaseStorageAreaLocationList = tBaseStorageAreaLocationMapper.selectFreeLoc(decid);
                if (tBaseStorageAreaLocationList.size() > 0) {
                    logger.info("生成移库任务=====》》》》》{}", locationId);
                    //判断改库位如果是在深库位，需要判断浅库位是否有货
                    String toLoc = StringUtils.EMPTY;
                    String decid11 = StringUtils.EMPTY;
                    for (TBaseStorageAreaLocation tBaseStorageAreaLocation : tBaseStorageAreaLocationList) {
                        if (tBaseStorageAreaLocation.getLocationId().endsWith("1")) {
                            String tempLocationId = tBaseStorageAreaLocation.getLocationId();
                            String locationY = tempLocationId.substring(0, tempLocationId.length() - 1) + "2";
                            TMiStock tMiStock5 = new TMiStock();
                            tMiStock5.setLocationId(locationY);
                            List<TMiStock> tMiStocks5 = tMiStockMapper.selectTMiStockList(tMiStock5);
                            if (tMiStocks5.size() == 0) {
                                logger.warn("深货位无库存，切换：{}", locationY);
                                continue;
                            }
                            //
                            TCkPickingwavegoods tCkPickingwavegoods5 = new TCkPickingwavegoods();
                            tCkPickingwavegoods5.setLocationId(locationY);
                            List<TCkPickingwavegoods> ckTypeList5 = tCkPickingwavegoodsMapper.selectList(new QueryWrapper<>(tCkPickingwavegoods5));
                            if (ckTypeList5.size() > 0) {
                                logger.warn("深货位有出库任务，切换：{}", locationY);
                                continue;
                            }
                            TCkPickingwavegoods tCkPickingwavegoods2 = new TCkPickingwavegoods();
                            tCkPickingwavegoods2.setCkType("3");
                            tCkPickingwavegoods2.setToLoc(tBaseStorageAreaLocation.getLocationId());
                            List<TCkPickingwavegoods> ckTypeList2 = tCkPickingwavegoodsMapper.selectList(new QueryWrapper<>(tCkPickingwavegoods2));
                            if (ckTypeList2.size() > 0) {
                                continue;
                            }
                            TOngoodsshelf tOngoodsshelf2 = new TOngoodsshelf();
                            tOngoodsshelf2.setLocationId(tBaseStorageAreaLocation.getLocationId());
                            List<TOngoodsshelf> tOngoodsshelves2 = tOngoodsshelfService.selectTOngoodsshelfList(tOngoodsshelf2);
                            if (tOngoodsshelves2.size() > 0) {
                                continue;
                            }
                            toLoc = tBaseStorageAreaLocation.getLocationId();
                            decid11 = tBaseStorageAreaLocation.getDecid();
                            break;
                        } else {
                            String tempLocationId = tBaseStorageAreaLocation.getLocationId();
                            String locationY = tempLocationId.substring(0, tempLocationId.length() - 1) + "1";
                            //
                            TCkPickingwavegoods tCkPickingwavegoods2 = new TCkPickingwavegoods();
                            tCkPickingwavegoods2.setCkType("3");
                            tCkPickingwavegoods2.setToLoc(locationY);
                            List<TCkPickingwavegoods> ckTypeList2 = tCkPickingwavegoodsMapper.selectList(new QueryWrapper<>(tCkPickingwavegoods2));
                            if (ckTypeList2.size() > 0) {
                                logger.warn("有移库任务，切换：{}", locationY);
                                continue;
                            }
                            TOngoodsshelf tOngoodsshelf2 = new TOngoodsshelf();
                            tOngoodsshelf2.setLocationId(locationY);
                            List<TOngoodsshelf> tOngoodsshelves2 = tOngoodsshelfService.selectTOngoodsshelfList(tOngoodsshelf2);
                            if (tOngoodsshelves2.size() > 0) {
                                logger.warn("有入库任务，切换：{}", locationY);
                                continue;
                            }
                            TMiStock tMiStock1 = new TMiStock();
                            tMiStock1.setLocationId(locationY);
                            List<TMiStock> tMiStocks1 = tMiStockMapper.selectTMiStockList(tMiStock1);
                            if (tMiStocks1.size() > 0) {
                                logger.warn("有库存，切换：{}", locationY);
                                continue;
                            }

                            toLoc = tBaseStorageAreaLocation.getLocationId();
                            decid11 = tBaseStorageAreaLocation.getDecid();
                            break;
                        }
                    }
//                         String toLoc = tBaseStorageAreaLocationList.get(0).getLocationId();
                    if (StringUtils.isBlank(toLoc)) {
                        logger.error("没有找到移库地址，出库失败");
                        throw new RuntimeException("没有找到移库地址，出库失败");
                    }
                    //创建出库任务
                    TCkPickingwavegoods tCkPickingwavegoods = new TCkPickingwavegoods();
                    String yc = OrderCodeFactory.getOrderCode("YK", "");
                    tCkPickingwavegoods.setPickingId(yc);
                    tCkPickingwavegoods.setPutinId(yc);
                    tCkPickingwavegoods.setCkType("3");
                    tCkPickingwavegoods.setLocationId(locationId);
                    tCkPickingwavegoods.setLocId(locationId);
                    tCkPickingwavegoods.setOutId(toLoc);
                    tCkPickingwavegoods.setToLoc(toLoc);
                    tCkPickingwavegoods.setCtl(transferCtl);
                    tCkPickingwavegoods.setStatus("0");
                    tCkPickingwavegoods.setDecId(transferDecid);
                    tCkPickingwavegoods.setUpdateTime(new Date());
                    LoginUser loginUser = SecurityUtils.getLoginUser();
                    tCkPickingwavegoods.setCustomerId("ERP出库移库：" + loginUser.getUser().getNickName());
                    tCkPickingwavegoodsService.insertTCkPickingwavegoods(tCkPickingwavegoods);
                    //冻结库位
                    TBaseStorageAreaLocation tBaseStorageAreaLocation = new TBaseStorageAreaLocation();
                    tBaseStorageAreaLocation.setStatus("1");
                    tBaseStorageAreaLocation.setLocationId(toLoc);
                    tBaseStorageAreaLocation.setDecid(decid11);

                    tBaseStorageAreaLocationMapper.updateLocationSts(tBaseStorageAreaLocation);
                    //锁定库存
                    TMiStock tMiStock3 = new TMiStock();
                    tMiStock3.setCtl(transferCtl);
                    tMiStock3.setStatus("1");
                    tMiStockMapper.updateSts(tMiStock3);
                }

            }
        }
        //设置库存里面的出库数量
        for (TMiStock tMiStock1 : tMiStocks) {
            for (String key : map.keySet()) {
                BigDecimal value = map.get(key);
                if (tMiStock1.getGoodsId().equals(key)) {
                    tMiStock1.setPackingNum(value);
                    break;
                }
            }
        }
        boolean isExist = false;
        for (TMiStock tMiStock1 : tMiStocks) {
            if (tMiStock1.getPackingNum() == null) {
                isExist = true;
                break;
            }
            if (tMiStock1.getShelvesNum().compareTo(tMiStock1.getPackingNum()) > 0) {
                isExist = true;
                break;
            }

        }
        //CkType ： 1.零捡 2：全量 3移库
        //boxtype：1：不需要出库 2：零捡 3：全出
        if (isExist) {
            tMiStocks.forEach(e -> {
                if (e.getPackingNum() == null) {
                    //不需要出库的
                    e.setBoxType("1");
                } else {
                    //零检
                    e.setBoxType("2");
                }
                e.setCkType("1");
            });
        } else {
            tMiStocks.forEach(e -> {
                e.setCkType("2");
                e.setBoxType("3");
            });
        }
        //是否需要冻结库存
        TMiStock tMiStock3 = new TMiStock();
        tMiStock3.setCtl(ctl);
        tMiStock3.setStatus("1");
        tMiStockMapper.updateSts(tMiStock3);
        //创建出库任务
        String code = OrderCodeFactory.getOrderCode("CK", "");
        for (TMiStock tMiStock1 : tMiStocks) {
            if (ctl.equals(tMiStock1.getCtl())) {
                TCkPickingwavegoods tCkPickingwavegoods = new TCkPickingwavegoods();
                tCkPickingwavegoods.setGoodsId(tMiStock1.getGoodsId());
                //图号
                tCkPickingwavegoods.setRecoil(tMiStock1.getOriBill());
                tCkPickingwavegoods.setCtl(tMiStock1.getCtl());
                tCkPickingwavegoods.setDecId(tMiStock1.getDecid());
                tCkPickingwavegoods.setGoodsName(tMiStock1.getGoodsName());
                tCkPickingwavegoods.setMistockNum(tMiStock1.getShelvesNum());
                //出库数量
                tCkPickingwavegoods.setGoodsNum(tMiStock1.getPackingNum());
                tCkPickingwavegoods.setRecNum(BigDecimal.ZERO);
                tCkPickingwavegoods.setLocationId(tMiStock1.getLocationId());
                tCkPickingwavegoods.setLocId(tMiStock1.getLocationId());
                tCkPickingwavegoods.setPickingId(code);
                tCkPickingwavegoods.setPutinId(code);
                tCkPickingwavegoods.setUnit(tMiStock1.getUnit());
                tCkPickingwavegoods.setDecId(tMiStock1.getDecid());
                tCkPickingwavegoods.setCkType(tMiStock1.getCkType());
                tCkPickingwavegoods.setTypests(tMiStock1.getBoxType());
                tCkPickingwavegoods.setWgh(tMiStock1.getWgh());
                //库存主键
                tCkPickingwavegoods.setProduclotId(String.valueOf(tMiStock1.getId()));
                tCkPickingwavegoods.setSpecification(tMiStock1.getSpecification());
                //出库单明细的orderId，出库单主键
                tCkPickingwavegoods.setSalesOrderNo(String.valueOf(orderId));
                tCkPickingwavegoods.setOutstand(tMiStock1.getStandard());
                LoginUser loginUser = SecurityUtils.getLoginUser();
                tCkPickingwavegoods.setCustomerId("ERP出库：" + loginUser.getUser().getNickName());
                tCkPickingwavegoods.setRemark("erp出库订单产生的出库任务");
//                tCkPickingwavegoods.setRecNum(BigDecimal.ZERO);
                logger.info("根据出库单创建出库任务：{}", tCkPickingwavegoods);
                tCkPickingwavegoodsService.insertTCkPickingwavegoods(tCkPickingwavegoods);
            }

        }
    }


    /**
     * 出库拣选，确认操作
     *
     * @param goodsList
     * @return
     */
    @Log(title = "出库拣选")
    @Transactional(rollbackFor = Exception.class)
    public int confirm(List<TCkPickingwavegoods> goodsList) {
        logger.info("确认出库开始：{}", goodsList);
        if (goodsList.size() == 0) {
            logger.error("拣选明细不能为空");
            throw new RuntimeException("拣选明细不能为空");
        }
        //托盘所有数据
        List<TCkPickingwavegoods> tCkPickingwavegoodsList = tCkPickingwavegoodsMapper.selectgoodsByCtl(goodsList.get(0));
        logger.info("获取数据：{}", tCkPickingwavegoodsList.size());
        if (tCkPickingwavegoodsList.size() == 0) {
            logger.error("未查询到待拣选任务");
            throw new RuntimeException("未查询到该托盘号待拣选任务");
        }
        if (tCkPickingwavegoodsList.size() != goodsList.size()) {
            logger.error("拣选确认必须同一个库位一起进行确认");
            throw new RuntimeException("拣选确认必须同一个库位一起进行确认");
        }

        //释放该库位
        //备份出库任务
        String id = StringUtils.EMPTY;
        String ctl = StringUtils.EMPTY;
        String storageId = StringUtils.EMPTY;
        String locationId = StringUtils.EMPTY;
        String callNoticeId = StringUtils.EMPTY;
        //更新主表状态
        TCkOrders tCkOrders5 = new TCkOrders();
        tCkOrders5.setId(goodsList.get(0).getOutId());
        tCkOrders5.setStatus("0");
        tCkOrdersMapper.updateById(tCkOrders5);

        for (TCkPickingwavegoods tCkPickingwavegoods : goodsList) {

            // 备份呼叫单号
            callNoticeId = tCkPickingwavegoods.getCallNoticeId();

            //更新库存
            updateTmiStock(tCkPickingwavegoods);

            // 1. 备份修改后的出库任务
            TCkPickingwavegoodsBak bak = new TCkPickingwavegoodsBak();
            BeanUtils.copyProperties(tCkPickingwavegoods,bak);
            bak.setConfirmStatus("3");
            tCkPickingwavegoodsBakService.insertTCkPickingwavegoodsBak(bak);

            //出库单出库数量
            TCkOrderdetail tCkOrderdetail = new TCkOrderdetail();
            tCkOrderdetail.setGoodsId(tCkPickingwavegoods.getGoodsId());
            //主表主键
            if (StringUtils.isBlank(id)) {
                id = tCkPickingwavegoods.getOutId();
                ctl = tCkPickingwavegoods.getCtl();
                storageId = tCkPickingwavegoods.getStorageId();
                locationId = tCkPickingwavegoods.getLocationId();
            }
            tCkOrderdetail.setOrderId(id);
            List<TCkOrderdetail> tCkOrderdetails = tCkOrderdetailMapper.selectTCkOrderdetailList(tCkOrderdetail);
            if (tCkOrderdetails.size() > 0) {
                TCkOrderdetail tCkOrderdetail1 = tCkOrderdetails.get(0);
                //确认出库数量
                if (tCkOrderdetail1.getTrNum() == null) tCkOrderdetail1.setTrNum(BigDecimal.ZERO);
                if (tCkPickingwavegoods.getRecNum() == null) tCkPickingwavegoods.setRecNum(BigDecimal.ZERO);
                tCkOrderdetail1.setTrNum(tCkOrderdetail1.getTrNum().add(tCkPickingwavegoods.getRecNum()));
                //清空上次出库数量
                tCkOrderdetail1.setGoodsNum(BigDecimal.ZERO);
                if (tCkOrderdetail1.getShelvesNum().compareTo(tCkOrderdetail1.getTrNum()) == 0) {
                    tCkOrderdetail1.setConfirmStatus("2");
                } else {
                    if ("0".equals(tCkOrderdetail1.getConfirmStatus())) {
                        tCkOrderdetail1.setConfirmStatus("1");
                    }
                }
                tCkOrderdetail1.setUpdateTime(DateUtils.getNowDate());
                tCkOrderdetail1.setStatus("0");
                tCkOrderdetailMapper.updateTCkOrderdetail(tCkOrderdetail1);
            }
        }

        //根据库位查询是否有库存
        LambdaQueryWrapper<TMiStock> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TMiStock::getLocationId,locationId);
//        queryWrapper.eq(TMiStock::getCtl,ctl);

        List<TMiStock> tMiStocks = tMiStockMapper.selectList(queryWrapper);
        if(tMiStocks.size() == 0){
            //释放库位
            TBaseStorageAreaLocation baseStorageAreaLocation = new TBaseStorageAreaLocation();
            baseStorageAreaLocation.setLocationId(locationId);
            baseStorageAreaLocation.setStatus("0");
            tBaseStorageAreaLocationMapper.updateLocationSts(baseStorageAreaLocation);
        }
        //校验托盘容器是否正确
        if(StringUtils.isNotBlank(ctl)){
        LambdaQueryWrapper<TMiStock> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(TMiStock::getCtl,ctl);
        List<TMiStock> tMiStocks2 = tMiStockMapper.selectList(queryWrapper);
        if(tMiStocks2.size() == 0){
            LambdaQueryWrapper<TBasePallet> ctlWrapper = new LambdaQueryWrapper<>();
            ctlWrapper.eq(TBasePallet::getPalletId, ctl);
            List<TBasePallet> plcs = basePalletMapper.selectList(ctlWrapper);
            if (!plcs.isEmpty()) {
                TBasePallet palletChk = plcs.get(0);
                if("1".equals(palletChk.getStatus())){
                    TBasePallet tBasePallet = new TBasePallet();
                    tBasePallet.setStatus("0");
                    tBasePallet.setId(palletChk.getId());
                    tBasePallet.setUpdateTime(new Date());
                    basePalletMapper.updateTBasePallet(tBasePallet);
                }
            }
        }
        }


//        else {
//            TMiStock tMiStock = new TMiStock();
//            tMiStock.setStorageId(storageId);
//            tMiStock.setCtl(ctl);
//            tMiStock.setStatus("0");
//            tMiStockMapper.updateSts(tMiStock);
//        }
        //查询通知单是否已经全部出库完成
        TCkOrderdetail tCkOrderdetail = new TCkOrderdetail();
        tCkOrderdetail.setOrderId(id);
        List<TCkOrderdetail> tCkOrderdetails = tCkOrderdetailMapper.selectTCkOrderdetailList(tCkOrderdetail);
        boolean isExist = false;
        for(TCkOrderdetail tCkOrderdetail1:tCkOrderdetails){
            if(!"2".equals(tCkOrderdetail1.getConfirmStatus())){
                isExist = true;
                break;
            }
        }
        //删除出库通知单 备份出库通知单
        TCkOrders tCkOrders = tCkOrdersMapper.selectTCkOrdersById(id);
        if(!isExist){
            TckOrdersBak tckOrdersBak =new TckOrdersBak();
            BeanUtils.copyProperties(tCkOrders,tckOrdersBak);
            LambdaQueryWrapper<TCkOrderdetail> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(TCkOrderdetail::getOrderId,id);
            List<TCkOrderdetail> tckOrderdetailList =  tCkOrderdetailMapper.selectList(queryWrapper1);
//            List<TCkOrderdetail> tckOrderdetailList = tCkOrders.getTckOrderdetailList();
            List<TckOrderdetailBak> bakList = new ArrayList<>();
            for(TCkOrderdetail tCkOrderdetail1 : tckOrderdetailList){
                TckOrderdetailBak tckOrderdetailBak = new TckOrderdetailBak();
                BeanUtils.copyProperties(tCkOrderdetail1,tckOrderdetailBak);
                //存储审核人和审核时间
                tckOrderdetailBak.setAuditDate(tCkOrders.getAuditDate());
                tckOrderdetailBak.setAuditMan(tCkOrders.getAuditMan());
                tckOrderdetailBak.setApplicant(tCkOrders.getApplicant());
                tckOrderdetailBak.setRejectReason(tCkOrders.getRejectReason());
                bakList.add(tckOrderdetailBak);
            }
            tckOrdersBak.setTckOrderdetailBakList(bakList);
            tckOrdersBakService.insertTckOrdersBak(tckOrdersBak);
            //删除
            tCkOrdersMapper.deleteTCkOrdersById(id);
            tCkOrdersMapper.deleteTCkOrderdetailByOrderId(id);

            //用于发送设备
            tCkOrders.setTckOrderdetailList(tckOrderdetailList);
            // 关闭出库通知单任务消息
            // TCallNoticeOrder tCallNotice = new TCallNoticeOrder();
            // tCallNotice.setTaskId(tCkOrders.getOrderId());
            // tCallNotice.setTaskType("0");
            // tCallNotice.setUpdateBy(SecurityUtils.getUsername());
            // tCallNotice.setUpdateTime(new Date());
            // tNoticeOrderService.updateTaskStatus(tCallNotice);

        }else{
            tCkOrders.setConfirmStatus("1");
            tCkOrdersMapper.updateConfirmStatus(tCkOrders);
        }

        // 2. 删除原有出库任务
        for(TCkPickingwavegoods tCkPickingwavegoods : goodsList) {
            tCkPickingwavegoods.setConfirmStatus("2");
            tCkPickingwavegoodsMapper.deleteGoods(tCkPickingwavegoods);
        }

        if (!StringUtils.isEmpty(callNoticeId)) {
            TCkPickingwavegoods tCkPgoods = new TCkPickingwavegoods();
            tCkPgoods.setCallNoticeId(callNoticeId);
            List<TCkPickingwavegoods> tCkPickingwavegoodList = tCkPickingwavegoodsMapper.selectTCkPickingwavegoodsList(tCkPgoods);

            // 不存在该呼叫任务号的出库任务（全部出库）
            if (tCkPickingwavegoodList.size() == 0) {
                // 关闭出库任务通知
                TCallNotice tCallNotice = new TCallNotice();
                tCallNotice.setId(callNoticeId);
                tCallNotice.setTaskType("1");
                tCallNotice.setUpdateBy(SecurityUtils.getUserNick());
                tCallNotice.setUpdateTime(new Date());
                tNoticeService.updateTaskStatus(tCallNotice);

                //发送设备
                String s = sendDevice(tCkOrders);
                if (s.equals("推送成功出库完成")){
                    return 1;
                }else {
                    return 0;
                }

            }
        }

        return 1;
    }


    @Log(title = "设备管理系统数据推送",businessType = BusinessType.TUISONG)
    public String sendDevice(TCkOrders tCkOrders) {
        // 获取签名
        String sign = StringUtils.EMPTY;
        try {
            sign = SignTool.generateSign(DeviceInfo.AKSKID, DeviceInfo.AK, DeviceInfo.SK);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("出库完成，产生签名失败，无法发送设备平台==>>>{}", tCkOrders);
            return "出库完成，产生签名失败，无法发送设备平台";
        }

        // 设置请求头
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json;charset=UTF-8");
        headers.put("Datalink-Sign", sign);
        headers.put("datalink-region", "SA");

        // 设置请求体
        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("workSpaceId", DeviceInfo.WORKSPACEID);
        reqMap.put("appId", DeviceInfo.APPID);
        reqMap.put("formId", DeviceInfo.FORMID);
        reqMap.put("primaryValidate", DeviceInfo.PRIMARYVALIDATE);
        reqMap.put("terminal", DeviceInfo.terminal);
        reqMap.put("permissionGroupId", DeviceInfo.permissionGroupId);

        List<Map<String, Object>> dataList = new ArrayList<>();
        for (TCkOrderdetail orderDetail : tCkOrders.getTckOrderdetailList()) {
            Map<String, Object> objMap = new HashMap<>();
            Map<String, Object> dataMap = new HashMap<>();
            //物料编码
            dataMap.put("16762714231051e323", orderDetail.getGoodsId());
            //物料名称
            dataMap.put("16730628000781fffc",orderDetail.getGoodsName());
            //物料分类
            dataMap.put("168630280159119fd9","橡塑制品");
            //出库单编号 主表id
            dataMap.put("167996646260610a52",orderDetail.getOrderId());
            //出库单日期
            dataMap.put("167996676942815d49", DateUtil.formatDate(tCkOrders.getRecordDate()));

//           批次号	168221810201118f6b
            //dataMap.put("168221810201118f6b",orderDetail.getBatchNo());
            dataMap.put("168221810201118f6b","2306120198-00012308110001");
            //
//           数量	16799843524131dcef
            dataMap.put("16799843524131dcef",orderDetail.getTrNum());
//           成本单价(元)	167996659624410000
            dataMap.put("167996659624410000",orderDetail.getPrice());
//           成本金额(元)	167996659930419d98
            dataMap.put("167996659930419d98",0);
//           含税单价(元)	16799666417161c2df
            dataMap.put("16799666417161c2df",0);
//           含税金额(元)	16799666405351ad3e
            dataMap.put("16799666405351ad3e",0);
//           单位	167627140151616e43
            dataMap.put("167627140151616e43",orderDetail.getUnit());

//           规格说明	16885354383311f996
            dataMap.put("16885354383311f996",orderDetail.getSpecification());
//           供应商	16885286378311586a
            dataMap.put("16885286378311586a",orderDetail.getProviderId());
//           仓库	167996683943010c1c
            dataMap.put("167996683943010c1c",orderDetail.getStorageId());
//           物料来源	168852880606217e05
            if(StringUtils.isBlank(orderDetail.getOriginal())){
                dataMap.put("168852880606217e05","仓储系统");
            }else{
                dataMap.put("168852880606217e05",orderDetail.getOriginal());
            }

//           税率	6uqmar
            dataMap.put("6uqmar",0);
//           申请人	168852830803817e1c
           // dataMap.put("168852830803817e1c",tCkOrders.getApplicant());
            dataMap.put("168852830803817e1c","lannanceshi");
//           维修中心	8uv8xq
            dataMap.put("8uv8xq","东区维修中心");
//           包机组	2usyjy 待测试
            dataMap.put("2usyjy","第一包机组");
//           领料部门	16885281379451def6
            dataMap.put("16885281379451def6",null);
//           领料时间	1upjlj
            dataMap.put("1upjlj",tCkOrders.getOrderDate());
            objMap.put("entityData",dataMap);
            dataList.add(objMap);
        }
        reqMap.put("data", dataList);

        // 将请求体转换为 JSON 字符串
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = null;
        try {
            jsonString = objectMapper.writeValueAsString(reqMap);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        System.out.println(jsonString);

        String ip = "https://iepm.rzport.com:38443/datalinkprobackend/aksk/formentity/entityManagement/batchSaveEntity";

        try {
            JSONObject result = HttpUtils.post(ip, jsonString, headers);
            String code = result.containsKey("code") ? result.getStr("code") : "500";
            String errMsg = result.containsKey("msg") ? result.getStr("msg") : "未知错误";

            // 记录日志
            DeviceLog deviceLog = new DeviceLog();
            deviceLog.setCode(code);
            deviceLog.setMsg(errMsg);
            deviceLog.setOrders(tCkOrders.getId());
            deviceLog.setObj(jsonString);
            deviceLogMapper.insertDeviceLog(deviceLog);

        } catch (Exception e) {
            // 处理超时或其他异常
            DeviceLog deviceLog = new DeviceLog();
            deviceLog.setCode("500");
            deviceLog.setMsg("请求超时或失败");
            deviceLog.setOrders(tCkOrders.getId());
            deviceLog.setObj(jsonString);
            deviceLogMapper.insertDeviceLog(deviceLog);
            logger.error("请求失败: {}", e.getMessage());
            return "出库完成，请求超时或失败";
        }
        return "推送成功出库完成";
    }



    /**
     * 更新库存
     * @param tCkPickingwavegoods
     */
    private void updateTmiStock(TCkPickingwavegoods tCkPickingwavegoods) {
       if(StringUtils.isBlank(tCkPickingwavegoods.getDoctNumber())){
           throw new RuntimeException("出库任务库存ID为空异常，请传入库存ID");
       }
        TMiStock tMiStock = tMiStockMapper.selectById(tCkPickingwavegoods.getDoctNumber());
        if (tCkPickingwavegoods.getRecNum() == null) tCkPickingwavegoods.setRecNum(BigDecimal.ZERO);
        tMiStock.setShelvesNum(tMiStock.getShelvesNum().subtract(tCkPickingwavegoods.getRecNum()));
        tMiStock.setUpdateTime(DateUtils.getNowDate());
        tMiStock.setUpdateBy(SecurityUtils.getUserNick());
        if(tMiStock.getShelvesNum().compareTo(BigDecimal.ZERO) == 0){
            tMiStockMapper.deleteById(tMiStock);
       }else{
            tMiStock.setStatus("0");
            tMiStock.setOccupyNum(BigDecimal.ZERO);
           tMiStockMapper.updateById(tMiStock);
       }
    }



}
