package com.zbf.system.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zbf.common.annotation.DataScope;
import com.zbf.common.annotation.DataSource;
import com.zbf.common.annotation.Log;
import com.zbf.common.core.domain.AjaxResult;
import com.zbf.common.core.domain.entity.SysDept;
import com.zbf.common.core.domain.entity.SysUser;
import com.zbf.common.core.domain.model.LoginUser;
import com.zbf.common.enums.DataSourceType;
import com.zbf.common.exception.ServiceException;
import com.zbf.common.utils.DateUtils;
import com.zbf.common.utils.OrderCodeFactory;
import com.zbf.common.utils.SecurityUtils;
import com.zbf.common.utils.StringUtils;
import com.zbf.common.utils.uuid.IdUtils;
import com.zbf.system.config.CommonConfig;
import com.zbf.system.config.D_Service;
import com.zbf.system.domain.*;
import com.zbf.system.domain.vo.GoodsVo;
import com.zbf.system.domain.vo.TCkOrdersVo;
import com.zbf.system.mapper.*;
import com.zbf.system.service.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
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 org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static com.zbf.common.utils.SecurityUtils.*;
import static com.zbf.common.utils.SecurityUtils.getUsername;

/**
 * 出库Service业务层处理
 *
 * @author tony
 * @date 2024-06-24
 */
@Service
public class TCkOrdersServiceImpl extends ServiceImpl<TCkOrdersMapper, TCkOrders> implements ITCkOrdersService //修改
{
    private static final Logger logger = LoggerFactory.getLogger(TCkOrdersServiceImpl.class);
    @Autowired
    private TCkOrdersMapper tCkOrdersMapper;
    @Autowired
    private TCkOrderdetailMapper tCkOrderdetailMapper;
    @Autowired
    private TMiStockMapper tMiStockMapper;
    @Autowired
    private TCkPickingwavegoodsMapper tCkPickingwavegoodsMapper;

    @Autowired
    private TRkWareNoticeMapper rkWareNoticeMapper;

    @Autowired
    private ITCallNoticeService tNoticeService;
    @Autowired
    private ITBaseStorageService baseStorageService;

    @Autowired
    private ITCallNoticeOrderService tNoticeOrderService;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    @Autowired
    private TCkOrderdetailMapper orderdetailMapper;

    @Autowired
    private TBasePalletMapper palletMapper;

    @Autowired
    private TCallNoticeMapper tCallNoticeMapper;
    @Resource
    private IOutBoundService outBoundService;

    @Autowired
    private SysUserPostMapper sysUserPostMapper;

    @Autowired
    private TBaseGoodsMapper goodsMapper;

    @Autowired
    private TBaseStorageMapper storageMapper;

    @Autowired
    private TRkWareNoticeTabMapper mapper;

    @Autowired

    private TransferOrderMapper transferOrderMapper;

    @Autowired
    private  SysDeptMapper sysDeptMapper;


    @Value("${deptmanager}")
    private String deptManager;
    @Value("${managerName}")
    private String managerName;

    @Autowired
    private D_Service d_service;




    /**
     * 查询出库
     *
     * @param id 出库主键
     * @return 出库
     */
    @Override
    public TCkOrders selectTCkOrdersById(String id) {
        return tCkOrdersMapper.selectTCkOrdersById(id);
    }

    /**
     * 查询出库
     *
     * @param id 出库主键
     * @return 出库
     */
    @Override
    public TCkOrders selectTCkOrdersByOrderId(String id) {
        return tCkOrdersMapper.selectTCkOrdersByOrderId(id);
    }

    /**
     * 查询出库
     *
     * @param id 出库主键
     * @return 出库
     */
    @Override
    public TCkOrders selectTCkOrdersByDeliveryId(String id) {
        return tCkOrdersMapper.selectTCkOrdersByDeliveryId(id);
    }


    /**
     * 查询出库列表
     *
     * @param tCkOrders 出库
     * @return 出库
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<TCkOrders> selectTCkOrdersList(TCkOrders tCkOrders) {
        List<TCkOrders> orders = tCkOrdersMapper.selectTCkOrdersList(tCkOrders);
        /*LoginUser loginUser = getLoginUser();
        SysUser user = loginUser.getUser();
        //岗位
        SysUserPost userPost = sysUserPostMapper.select(user.getUserId());
        if (userPost==null){
            return orders;
        }
        if (userPost.getPostId()==6){
            return orders;
        }
        List<TCkOrders> collect = orders.stream().filter(c -> c.getApplicant().equals(SecurityUtils.getUserNick())).collect(Collectors.toList());*/
        return orders;
    }

    /**
     * 新增出库
     *
     * @param tCkOrders 出库
     * @return 结果
     */
    @Transactional
    @Override
    public int insertTCkOrders(TCkOrders tCkOrders) {
        tCkOrders.setCreateTime(DateUtils.getNowDate());
        tCkOrders.setStatus("0");
        //根据通知单号查询是否存在
        String deliveryId = tCkOrders.getDeliveryId();
        LambdaQueryWrapper<TCkOrders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TCkOrders::getDeliveryId, deliveryId);
        List<TCkOrders> tCkOrders1 = tCkOrdersMapper.selectList(queryWrapper);
        if (tCkOrders1.size() > 0) {
            throw new RuntimeException("来源单号已存在，请修改后再提交！");
        }
        if(StringUtils.isEmpty(tCkOrders.getApplicant())){
            tCkOrders.setApplicant(SecurityUtils.getUserNick());
        }else{
            tCkOrders.setApplicant(tCkOrders.getApplicant());
        }
        SysDept sysDept = sysDeptMapper.selectDeptById(tCkOrders.getDeptId());
        String[] split = sysDept.getAncestors().split(",");
        if(split.length>3){
            SysDept sysDept1 = sysDeptMapper.selectDeptById(Long.valueOf(split[3]));
            tCkOrders.setDeptName(sysDept1.getDeptName());
        }else{
            tCkOrders.setDeptName(sysDept.getDeptName());
        }


        tCkOrders.setRecordPerson(SecurityUtils.getUserNick());
        int rows = tCkOrdersMapper.insertTCkOrders(tCkOrders);
//        insertTCkOrderdetail(tCkOrders);
        return rows;
    }

    /**
     * 修改出库
     *
     * @param tCkOrders 出库
     * @return 结果
     */
    @Transactional
    @Override
    public int updateTCkOrders(TCkOrders tCkOrders) {
        tCkOrders.setUpdateTime(DateUtils.getNowDate());
       LoginUser loginUser = SecurityUtils.getLoginUser();
        if(loginUser != null){
            SysUser user = loginUser.getUser();
            if(user != null){
                tCkOrders.setUpdateBy(user.getNickName());
            }
        }else{
            tCkOrders.setUpdateBy("callBack 更新");
        }

//        String orderId = tCkOrders.getOrderId();
//        LambdaQueryWrapper<TCkOrders> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(TCkOrders::getOrderId, orderId);
//        List<TCkOrders> tCkOrders1 = tCkOrdersMapper.selectList(queryWrapper);
//        if (tCkOrders1.size() > 1) {
//            throw new RuntimeException("来源单号已存在，请修改后再提交！");
//        }
//        if (tCkOrders1.size() == 1) {
//            TCkOrders tCkOrders2 = tCkOrders1.get(0);
//            if (!tCkOrders2.getId().equals(tCkOrders.getId())) {
//                throw new RuntimeException("来源单号已存在，请修改后再提交！");
//            }
//        }
//        tCkOrdersMapper.deleteTCkOrderdetailByOrderId(tCkOrders.getId());
//        insertTCkOrderdetail(tCkOrders);
        return tCkOrdersMapper.updateTCkOrders(tCkOrders);
    }

    /**
     * 批量删除出库
     *
     * @param ids 需要删除的出库主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteTCkOrdersByIds(String[] ids) {
        tCkOrdersMapper.deleteTCkOrderdetailByOrderIds(ids);
        return tCkOrdersMapper.deleteTCkOrdersByIds(ids);
    }

    /**
     * 删除出库信息
     *
     * @param id 出库主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteTCkOrdersById(String id) {
        tCkOrdersMapper.deleteTCkOrderdetailByOrderId(id);
        return tCkOrdersMapper.deleteTCkOrdersById(id);
    }


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

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

    /**
     * 修改状态
     *
     * @param tCkOrders 工序管理主键
     * @return 结果
     */
    @Override
    @Transactional
    public int updateStatus(TCkOrders tCkOrders) {
        if (StringUtils.isNotBlank(tCkOrders.getIsAudit())) {
            if (StringUtils.isNotBlank(tCkOrders.getAuditPerson1())) {
                this.deptManager = tCkOrders.getAuditPerson1();
            }
            if (StringUtils.isNotBlank(tCkOrders.getAuditPerson2())) {
                this.managerName = tCkOrders.getAuditPerson2();
            }
            //tCkOrders.setAuditMan(deptManager);
            tCkOrders.setRejectReason("");
        }


        TCkOrders tCkOrders1 = tCkOrdersMapper.get(tCkOrders.getId());
        OutBound outBound = new OutBound();
        outBound.setDeptmanager(deptManager); //第一审核人
        outBound.setManagerName(managerName); //第二审核人
        outBound.setDeliveryId(tCkOrders1.getDeliveryId());
        outBound.setCkType(tCkOrders1.getCkType());
        outBound.setApplyTime(DateUtils.getDate());
//        outBound.setApplyer(SecurityUtils.getUserNick());
        outBound.setApplyer(getUsername());
        if (StringUtils.isNotBlank(tCkOrders.getAuditPerson3())) {
            outBound.setCrossDeptManager(tCkOrders.getAuditPerson3());
        }

        List<GoodsVo> goodsVos = new ArrayList<>();
        //查询明细
        TCkOrderdetail tCkOrderdetail = new TCkOrderdetail();
        tCkOrderdetail.setOrderId(tCkOrders.getId());
        List<TCkOrderdetail> tCkOrderdetailList = tCkOrderdetailMapper.selectTCkOrderdetailList(tCkOrderdetail);
        if(tCkOrderdetailList.size() == 0){
            logger.error("没有获取到明细条数====");
            throw new RuntimeException("未获取到明细，请确认！");
        }
        String storageId = StringUtils.EMPTY;
        for (TCkOrderdetail tCkOrderdetail1 : tCkOrderdetailList) {
            GoodsVo goodsVo = new GoodsVo();
            goodsVo.setId(tCkOrderdetail1.getId());
            goodsVo.setGoodsId(tCkOrderdetail1.getGoodsId());
            goodsVo.setGoodsName(tCkOrderdetail1.getGoodsName());
            goodsVo.setPrice(tCkOrderdetail1.getPrice());
            goodsVo.setUnit(tCkOrderdetail1.getUnit());
            goodsVo.setShelvesNum(tCkOrderdetail1.getShelvesNum());
            goodsVo.setStorageId(tCkOrderdetail1.getStorageId());
            goodsVo.setStorageShortName(tCkOrderdetail1.getStorageShortName());
            if(StringUtils.isBlank(storageId)){
                storageId = tCkOrderdetail1.getStorageShortName();
            }
            goodsVo.setTotal(tCkOrderdetail1.getStockNum());
            goodsVo.setRemark(tCkOrderdetail1.getRemark());
            //物资流向
            goodsVo.setGoodsTo(tCkOrderdetail1.getGoodsTo());

            goodsVo.setLevelType(tCkOrderdetail1.getLevelType());
            goodsVo.setSpecification(tCkOrderdetail1.getSpecification());
            goodsVo.setRecoil(tCkOrderdetail1.getRecoil());

            goodsVos.add(goodsVo);
            //更新呼叫数量
            TCkOrderdetail tCkOrderdetail2 = new TCkOrderdetail();
            tCkOrderdetail2.setId(tCkOrderdetail1.getId());
            tCkOrderdetail2.setCallShelvesNum(tCkOrderdetail1.getShelvesNum());
            tCkOrderdetailMapper.updateTCkOrderdetail(tCkOrderdetail2);
        }
        outBound.setStorageId(storageId);
        outBound.setItemList(JSONUtil.toJsonStr(goodsVos));
        //查询token，创建实例
        String instance = d_service.createInstance(outBound);
        logger.info("创建的实例ID：{}",instance);
        if(StringUtils.isBlank(instance)){
            logger.warn("创建实例ID异常,只能本地审批，无法通过钉钉审批了，流程继续，申请人：{}",getUsername());
            //throw new RuntimeException("创建钉钉实例异常===》》》》");
        }
        outBound.setInstanceId(instance);
        outBoundService.insertOutBound(outBound);
        //更新出库主表钉钉实例ID
        tCkOrders.setInstanceId(instance);
        int row = tCkOrdersMapper.updateTCkOrders(tCkOrders);
        return row;
    }

    @Transactional
    @Override
    public int auditCkOrdersTCkOrdersByIds(String[] ids) {
        return tCkOrdersMapper.auditTCkOrdersByIds(ids, SecurityUtils.getUserNick(), DateUtils.getNowDate());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTCkOrdersDetails(List<TCkOrderdetail> tCkOrderdetails) {
        //根据goodsId判断是否有重复的 用lanmada表达式
        // 判断是否存在重复的GoodsId
        boolean hasDuplicate = tCkOrderdetails.stream()
                .collect(Collectors.groupingBy(TCkOrderdetail::getGoodsId))
                .values()
                .stream()
                .anyMatch(list -> list.size() > 1);
        if(hasDuplicate){
            throw new RuntimeException("请不要添加重复的物料");
        }

        for (TCkOrderdetail orderdetail : tCkOrderdetails) {
            //需求数量
            BigDecimal shelvesNum = orderdetail.getShelvesNum();
            orderdetail.setGoodsNum(shelvesNum);
//            if (StringUtils.isBlank(orderdetail.getBusinessId())) {
//                orderdetail.setBusinessId("RK"+generateReqCode());
//            }
            //物料id不能重复
            LambdaQueryWrapper<TCkOrderdetail> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TCkOrderdetail::getOrderId, orderdetail.getOrderId());
            queryWrapper.eq(TCkOrderdetail::getGoodsId, orderdetail.getGoodsId());
            List<TCkOrderdetail> tCkOrderdetails1 = tCkOrderdetailMapper.selectList(queryWrapper);
            for (TCkOrderdetail ckOrderdetail : tCkOrderdetails) {
                LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(TMiStock::getGoodsId, ckOrderdetail.getGoodsId());
                wrapper.eq(TMiStock::getStatus, "1");
                List<TMiStock> tMiStocks = tMiStockMapper.selectList(wrapper);
                if (!tMiStocks.isEmpty()) {
                    throw new RuntimeException(ckOrderdetail.getGoodsName() + "物料已被冻结");
                }
            }
            String goodsId = orderdetail.getGoodsId();
            LambdaQueryWrapper<TBaseGoods> goods = new LambdaQueryWrapper<>();
            goods.eq(TBaseGoods::getGoodsId, goodsId);
            TBaseGoods tBaseGoods = goodsMapper.selectOne(goods);
            //原来仓库
            //总价
            BigDecimal price = tBaseGoods.getPrice();
            // 设置默认值
            if (price == null || price.compareTo(BigDecimal.ZERO) == 0) {
                price = BigDecimal.ZERO; // 默认值为 1
            }
            orderdetail.setPrice(price);
            BigDecimal totalPrice = price.multiply(shelvesNum);
            orderdetail.setToMoney(totalPrice);


            orderdetail.setUpdateTime(DateUtils.getNowDate());
            orderdetail.setCreateTime(DateUtils.getNowDate());
            orderdetail.setConfirmStatus("0");
            if (StringUtils.isNotBlank(orderdetail.getId())) {
                if (tCkOrderdetails1.size() > 1) {
                    throw new RuntimeException("更新物料重复异常");
                }

                tCkOrderdetailMapper.update(orderdetail, queryWrapper);
            } else {
                if (tCkOrderdetails1.size() > 0) {
                    throw new RuntimeException("新增物料重复异常");
                }
                orderdetail.setId(OrderCodeFactory.getOrderCode("CKTM", ""));
                //todo 暂时通过remark记录物资流向
                if(StringUtils.isNotBlank(orderdetail.getRemark())) {
                    orderdetail.setGoodsTo(orderdetail.getRemark());
                }
                tCkOrderdetailMapper.insert(orderdetail);
            }
        }
        return 1;
    }

    @Override
    @Transactional
    public int deleteTCkOrderDetailsByIds(String[] ids) {
        tCkOrderdetailMapper.deleteBatchIds(Arrays.asList(ids));
        return 1;
    }

    @Override
    @Transactional
    public int confirmOut(TCkOrders tCkOrders) {
        List<TCkOrderdetail> tCkOrderdetailList = tCkOrders.getTckOrderdetailList();
        if (tCkOrderdetailList.size() == 0) {
            logger.error("出库明细条数必须大于0");
            throw new RuntimeException("出库明细条数必须大于0");
        }
        //1. 判断库存是否满足
//        String storageId = tCkOrders.getStorageId();
        //判断是否选中了仓库，如果没有选中，则从所有权限下仓库进行查询，如果选中了，则从指定仓库选择
        logger.info("出库请求解析开始：{}", tCkOrderdetailList);
        //value: 以托盘号为key，该托盘出库该物料的出库数量为value的map
        Map<String, Map<String, BigDecimal>> goodsMap = new HashMap<String, Map<String, BigDecimal>>();
        List<OutStockVo> outStockVos = new ArrayList<>();

        // 所有仓库集合
        List<String> totalStorageList = new ArrayList<>();

        for (TCkOrderdetail orderdetail : tCkOrderdetailList) {
            if ("2".equals(orderdetail.getConfirmStatus())) {
                logger.info("已出库完成的忽略：{}", orderdetail.getGoodsId());
                continue;
            }

            Map<String, BigDecimal> locationMap = new HashMap<>();
            TMiStock tMiStock = new TMiStock();
            tMiStock.setGoodsId(orderdetail.getGoodsId());
            tMiStock.setGoodsName(orderdetail.getGoodsName());

            if (StringUtils.isNotBlank(orderdetail.getStorageId())) {
                tMiStock.setStorageId(orderdetail.getStorageId());
            } else {
                TBaseStorage baseStorage = new TBaseStorage();
                baseStorage.setDeptId(tCkOrders.getDeptId());
                List<TBaseStorage> tBaseStorages = baseStorageService.selectTBaseStorageList(baseStorage);
                tMiStock.setStorageList(tBaseStorages.stream().map(TBaseStorage::getStorageId).collect(Collectors.toList()));
            }

            if(StringUtils.isNotBlank(orderdetail.getCtl())){
                tMiStock.setCtl(orderdetail.getCtl());
            }
            if(StringUtils.isNotBlank(orderdetail.getLocationId())){
                tMiStock.setLocationId(orderdetail.getLocationId());
            }

//            LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
//            wrapper.eq(TMiStock::getGoodsId, tMiStock.getGoodsId());
//            wrapper.eq(TMiStock::getGoodsName, tMiStock.getGoodsName());

            List<TMiStock> tMiStocks = tMiStockMapper.selectTMiStockList(tMiStock);

            if (tMiStocks.size() == 0) {
                logger.warn("未找到该物料库存或在冻结中：{}", orderdetail.getGoodsId());
                throw new RuntimeException("未找到该物料库存或在冻结中：" + orderdetail.getGoodsId());
            }

            // 分组逻辑：如果指定了 ctl，则只处理该 ctl 分组；否则按 locationId 分组，并只取每组的第一条
            String specifiedCtl = orderdetail.getCtl(); // 假设从 orderdetail 中获取 ctl
            Map<String, List<TMiStock>> groupedStocks;
            if (StringUtils.isNotBlank(specifiedCtl)) {
                groupedStocks = tMiStocks.stream()
                        .collect(Collectors.groupingBy(TMiStock::getCtl));
            } else {
                groupedStocks = tMiStocks.stream()
                        .collect(Collectors.groupingBy(TMiStock::getLocationId));
            }

            BigDecimal goodsNum = orderdetail.getGoodsNum();
            BigDecimal total = BigDecimal.ZERO;

            // 处理分组
           StringBuilder sb = new StringBuilder();
            for (List<TMiStock> stocks : groupedStocks.values()) {
                TMiStock tMiStock1 = stocks.get(0); // 取每组的第一条记录
                total = total.add(tMiStock1.getShelvesNum());
                if (orderdetail.getPickNum() == null) {
                    orderdetail.setPickNum(BigDecimal.ZERO);
                }
                OutStockVo outStockVo = new OutStockVo();
                outStockVo.setId(tMiStock1.getId());
                outStockVo.setLocationId(tMiStock1.getLocationId());

                if (goodsNum.compareTo(total) == 0) {
                    locationMap.put(tMiStock1.getLocationId(), tMiStock1.getShelvesNum());
                    outStockVo.setShelvesNum(tMiStock1.getShelvesNum());
                    outStockVos.add(outStockVo);
                    orderdetail.setPickNum(orderdetail.getPickNum().add(tMiStock1.getShelvesNum()));
                    sb.append(tMiStock1.getSalesOrderNumber()).append(",");
                    totalStorageList.add(tMiStock1.getStorageId());
                    break;
                } else if (goodsNum.compareTo(total) > 0) {
                    locationMap.put(tMiStock1.getLocationId(), tMiStock1.getShelvesNum());
                    outStockVo.setShelvesNum(tMiStock1.getShelvesNum());
                    outStockVos.add(outStockVo);
                    orderdetail.setPickNum(orderdetail.getPickNum().add(tMiStock1.getShelvesNum()));
                    sb.append(tMiStock1.getSalesOrderNumber()).append(",");
                    totalStorageList.add(tMiStock1.getStorageId());
                } else {
                    BigDecimal subtract = total.subtract(goodsNum);
                    BigDecimal subtract1 = tMiStock1.getShelvesNum().subtract(subtract);
                    locationMap.put(tMiStock1.getLocationId(), subtract1);
                    outStockVo.setShelvesNum(subtract1);
                    outStockVos.add(outStockVo);
                    orderdetail.setPickNum(orderdetail.getPickNum().add(subtract1));
                    sb.append(tMiStock1.getSalesOrderNumber()).append(",");
                    totalStorageList.add(tMiStock1.getStorageId());
                    break;
                }
            }
            if(sb.toString().length()>1){
                String substring = sb.substring(0, sb.length()-1);
                orderdetail.setBusinessId(substring);
            }
            goodsMap.put(orderdetail.getGoodsId(), locationMap);
            logger.info("更新累计出库数量：{}", orderdetail);
            orderdetail.setConfirmStatus("0");
            tCkOrderdetailMapper.updateTCkOrderdetail(orderdetail);
        }

        if (goodsMap.isEmpty()) {
            logger.warn("未找到出库物料");
            throw new RuntimeException("未找到出库物料,请确认！");
        }

        //设置主表status为锁定
        TCkOrders tCkOrders1 = new TCkOrders();
        tCkOrders1.setStatus("1");
        tCkOrders1.setId(tCkOrders.getId());
        tCkOrders1.setUpdateBy(SecurityUtils.getUserNick());
        tCkOrders1.setUpdateTime(new Date());
        tCkOrdersMapper.updateById(tCkOrders1);

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

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

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

            });
        });

        logger.info("生成以库位编号为主键的map：{}", locationGoodsMap);

        // 发送呼叫任务
        TCallNotice tCallNotice = new TCallNotice();
        tCallNotice.setId(IdUtils.randomUUID());

        //根据每个托盘创建出库任务
        //1. 判断出库任务是否已产生该托盘的任务

        locationGoodsMap.forEach((key, value) -> {
            TCkPickingwavegoods tCkPickingwavegoods = new TCkPickingwavegoods();
            tCkPickingwavegoods.setLocationId(key);
            tCkPickingwavegoods.setGoodsIdList(new ArrayList(value.keySet()));
            tCkPickingwavegoods.setOutId(tCkOrders.getId());
            //判断该库位编号是否产生出库任务
            List<TCkPickingwavegoods> tCkPickingwavegoodsList = tCkPickingwavegoodsMapper.selectTCkPickingwavegoodsList(tCkPickingwavegoods);
            if (tCkPickingwavegoodsList.size() > 0) {
                logger.error("该库位已产生出库任务：{}", key);
                throw new RuntimeException("该库位已产生出库任务：" + key);
            }

            //出库  添加呼叫任务号
            setCk(key, value, tCkOrders.getId(), tCkOrders.getOrderId(), tCkOrders.getCkType(),
                    outStockVos.stream().filter(stock -> stock.getLocationId().equals(key)).collect(Collectors.toList()),
                    tCallNotice.getId());

        });

        // 仓库ID去重
        totalStorageList = totalStorageList.stream().distinct().collect(Collectors.toList());

        totalStorageList.forEach((key) -> {
            // 仓库id
            tCallNotice.setStorageId(key);
            // 托盘号
            // tCallNotice.setCtl("");
            // pLCID
            // tCallNotice.setPlcid("");
            // 任务类型 1:出库任务
            tCallNotice.setTaskType("1");
            // 物料编码
            // tCallNotice.setGoodsId(tCkPickingwavegoods.getGoodsId());
            // 物料名称
            // tCallNotice.setGoodsName(tCkPickingwavegoods.getGoodsName());
            // 出库任务ID
            // tCallNotice.setChukuId(tCkPickingwavegoods.getId());
            // 创建者
            tCallNotice.setCreateBy(SecurityUtils.getUserNick());
            // 时间
            tCallNotice.setCreateTime(new Date());
            // 状态 0：未处理
            tCallNotice.setStatus("0");
            // 出库通知单号
            tCallNotice.setTaskId(tCkOrders.getOrderId());
            // 虚拟入库标识 0:非虚拟
            tCallNotice.setFictitious("0");

            tNoticeService.sendNotice(tCallNotice);
        });

        return 1;
    }

    //主页统计出库通知单
    @DataSource(DataSourceType.MASTER)
    @Override
    @DataScope(deptAlias = "d")
    public int homeOutCount(TCkOrders tCkOrders) {
        return tCkOrdersMapper.homeCount(tCkOrders);
    }

    //主页统计入库通知单
    @DataSource(DataSourceType.MASTER)
    @Override
    @DataScope(deptAlias = "d")
    public int homeInCount(TRkWareNotice tRkWareNotice) {
        return rkWareNoticeMapper.homeCount(tRkWareNotice);
    }

    /**
     * 新增出库物料明细信息
     *
     * @param tCkOrders 出库对象
     */
    public void insertTCkOrderdetail(TCkOrders tCkOrders) {
        List<TCkOrderdetail> tCkOrderdetailList = tCkOrders.getTckOrderdetailList();
        String id = tCkOrders.getId();
        if (StringUtils.isNotNull(tCkOrderdetailList)) {
            List<TCkOrderdetail> list = new ArrayList<TCkOrderdetail>();
            for (TCkOrderdetail tCkOrderdetail : tCkOrderdetailList) {
                tCkOrderdetail.setOrderId(id);
                list.add(tCkOrderdetail);
            }
            if (list.size() > 0) {
                tCkOrdersMapper.batchTCkOrderdetail(list);
            }
        }
    }

    private void setCk(String locationId, Map<String, BigDecimal> map,
                       String id, String orderId, String ckType
            , List<OutStockVo> outStockVos, String callNoticeId) {
        if (outStockVos.size() == 0) {
            throw new RuntimeException("没有获取到该物料库存明细");
        }
//        TMiStock tMiStock = new TMiStock();
//        tMiStock.setLocationId(locationId);
//        List<TMiStock> tMiStocks = tMiStockMapper.selectTMiStockList(tMiStock);

        //设置库存里面的出库数量
//        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");
//            });
//        }
        //是否需要冻结库存
        //出哪条，锁定哪条
        for (OutStockVo v : outStockVos) {
            TMiStock tMiStock3 = new TMiStock();
            tMiStock3.setId(v.getId());
            tMiStock3.setUpdateTime(DateUtils.getNowDate());
            tMiStock3.setUpdateBy(SecurityUtils.getUserNick());
            tMiStock3.setOccupyNum(v.getShelvesNum());
            tMiStock3.setStatus("1");
            tMiStockMapper.updateById(tMiStock3);
        }
//        TMiStock tMiStock3 = new TMiStock();
//        tMiStock3.setLocationId(locationId);
//        tMiStock3.setStatus("1");
//        tMiStock3.setUpdateBy(SecurityUtils.getUserNick());
//        tMiStock3.setUpdateTime(DateUtils.getNowDate());
//        tMiStockMapper.updateSts(tMiStock3);

        //创建出库任务
        for (OutStockVo outStockVo : outStockVos) {
            String code = OrderCodeFactory.getOrderCode("CK", "");
            TCkPickingwavegoods tCkPickingwavegoods = new TCkPickingwavegoods();
            TMiStock tMiStock1 = tMiStockMapper.selectById(outStockVo.getId());
            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(outStockVo.getShelvesNum());
            tCkPickingwavegoods.setRecNum(BigDecimal.ZERO);
            tCkPickingwavegoods.setLocationId(tMiStock1.getLocationId());
            tCkPickingwavegoods.setLocId(tMiStock1.getLocationId());
            tCkPickingwavegoods.setId(code);
            tCkPickingwavegoods.setPutinId(tMiStock1.getBatchNo());
            //来源单号
            tCkPickingwavegoods.setPickingId(orderId);
            tCkPickingwavegoods.setUnit(tMiStock1.getUnit());
            //出库类型
            tCkPickingwavegoods.setCkType(ckType);
            tCkPickingwavegoods.setTypests(tMiStock1.getBoxType());
            //待拣选
            tCkPickingwavegoods.setConfirmStatus("0");
            tCkPickingwavegoods.setWgh(tMiStock1.getWgh());
            //库存主键
            tCkPickingwavegoods.setDoctNumber(tMiStock1.getId());
            tCkPickingwavegoods.setSpecification(tMiStock1.getSpecification());
            //销售单号
            tCkPickingwavegoods.setSalesOrderNo(tMiStock1.getSalesOrderNo());
            tCkPickingwavegoods.setWareDate(tMiStock1.getWareDate());
            tCkPickingwavegoods.setSalesOrderNumber(tMiStock1.getSalesOrderNumber());
            tCkPickingwavegoods.setOutstand(tMiStock1.getStandard());
            tCkPickingwavegoods.setSpecification(tMiStock1.getSpecification());
            tCkPickingwavegoods.setProductionDate(tMiStock1.getProductionDate());
            tCkPickingwavegoods.setProviderId(tMiStock1.getProviderId());
            //出库单号
            tCkPickingwavegoods.setOutId(id);
            tCkPickingwavegoods.setStorageId(tMiStock1.getStorageId());
            tCkPickingwavegoods.setStorageShortName(tMiStock1.getStorageShortName());
            tCkPickingwavegoods.setStorageAreaId(tMiStock1.getStorageAreaId());
            //收货组织
            tCkPickingwavegoods.setProduclotId(tMiStock1.getProduclotId());
            tCkPickingwavegoods.setOperatorId(tMiStock1.getOperatorId());
            tCkPickingwavegoods.setSupplier(tMiStock1.getSupplier());
            tCkPickingwavegoods.setCustomerId(tMiStock1.getCustomerId());
            tCkPickingwavegoods.setBrand(tMiStock1.getBrand());
            tCkPickingwavegoods.setGoodsTypeId(tMiStock1.getGoodsTypeId());
            tCkPickingwavegoods.setCreateTime(DateUtils.getNowDate());
            tCkPickingwavegoods.setCreateBy(SecurityUtils.getUserNick());
            tCkPickingwavegoods.setDeptId(getLoginUser().getDeptId());
            // 呼叫任务号
            tCkPickingwavegoods.setCallNoticeId(callNoticeId);
            logger.info("根据出库单创建出库任务：{}", tCkPickingwavegoods);
            tCkPickingwavegoodsMapper.insertTCkPickingwavegoods(tCkPickingwavegoods);
        }
    }

    /**
     * 导入出库通知单数据
     *
     * @param dataList        用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operName        操作用户
     * @return 结果
     */
    @Override
    @Transactional
    public String importData(List<TCkOrderdetail> dataList, boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(dataList) || dataList.size() == 0) {
            throw new ServiceException("导入入库通知单数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        TCkOrderdetail tCkOrderdetailb1 = dataList.get(0);

        tCkOrderdetailb1.setDeliveryId(generateRandomHexCode(8));
        TCkOrders tCkOrders = new TCkOrders();
        tCkOrders.setDeliveryId(tCkOrderdetailb1.getDeliveryId());
        List<TCkOrders> tCkOrderss = tCkOrdersMapper.selectTCkOrdersList(tCkOrders);
        if (tCkOrderss.size() == 0) {
            setTckOrders(tCkOrders, tCkOrderdetailb1, operName);
            tCkOrdersMapper.insertTCkOrders(tCkOrders);
        } else if (isUpdateSupport) {
            List<String> collect = tCkOrderss.stream().map(TCkOrders::getId).collect(Collectors.toList());
            tCkOrdersMapper.deleteTCkOrdersByIds(collect.toArray(new String[collect.size()]));
            setTckOrders(tCkOrders, tCkOrderdetailb1, operName);
            tCkOrdersMapper.insertTCkOrders(tCkOrders);

        } else {
            throw new ServiceException("来源单号 " + tCkOrderdetailb1.getDeliveryId() + " 重复导入异常！");
        }


        for (int i = 0; i < dataList.size(); i++) {
            try {
                //校验必输字段
                TCkOrderdetail tab = dataList.get(i);
                checkData(i, tab);
                // 验证是否存在该明细
                TCkOrderdetail tCkOrderdetail = new TCkOrderdetail();
                tCkOrderdetail.setDeliveryId(tab.getDeliveryId());
                tCkOrderdetail.setGoodsId(tab.getGoodsId());
                tCkOrderdetail.setLevelType("2");

                List<TCkOrderdetail> tCkOrderdetailList = tCkOrderdetailMapper.selectTCkOrderdetailList(tCkOrderdetail);
                LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(TMiStock::getGoodsId, tab.getGoodsId());
                TMiStock tMiStock = tMiStockMapper.selectOne(wrapper);
                if (tMiStock.getStatus().equals("1")) {
                    successNum++;
                    failureMsg.append("<br/>" + tMiStock.getGoodsId() + "、物料编号 " + tab.getGoodsNum() + " 已锁定");
                }
                if (tCkOrderdetailList.size() == 0) {
                    setTab(tab, tCkOrders.getId(), operName);
                    tCkOrderdetailMapper.insertTCkOrderdetail(tab);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、物料编号 " + tab.getGoodsId() + " 导入成功");
                } else if (isUpdateSupport) {
                    List<String> collect = tCkOrderdetailList.stream().map(TCkOrderdetail::getId).collect(Collectors.toList());
                    tCkOrderdetailMapper.deleteTCkOrderdetailByIds(collect.toArray(new String[collect.size()]));
                    setTab(tab, tCkOrders.getId(), operName);
                    tCkOrderdetailMapper.insertTCkOrderdetail(tab);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、物料编号 " + tab.getGoodsId() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、物料编号 " + tab.getGoodsId() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、来源单号 " + tCkOrderdetailb1.getDeliveryId() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    private static Random random = new Random();

    private String generateRandomHexCode(int length) {
        // 生成一个以"rfid"开头的12位数字字符串
        String prefix = "LY";
        int numberLength = length; // 需要生成的数字长度
        StringBuilder numberBuilder = new StringBuilder();
        for (int i = 0; i < numberLength; i++) {
            numberBuilder.append(random.nextInt(10)); // 生成一个0到9的随机数
        }
        String rfid = prefix + numberBuilder.toString();
        return rfid;
    }

    private void setTab(TCkOrderdetail tab, String id, String operName) {
        tab.setId(OrderCodeFactory.getOrderCode("", ""));
        tab.setOrderId(id);
        tab.setCreateBy(operName);
        tab.setCreateTime(DateUtils.getNowDate());
        //二级入库
        tab.setLevelType("2");
        tab.setPickNum(BigDecimal.ZERO);
    }

    private void setTckOrders(TCkOrders tCkOrders, TCkOrderdetail tCkOrderdetail, String operName) {
        tCkOrders.setId(OrderCodeFactory.getOrderCode("", ""));
        tCkOrders.setOrderId(OrderCodeFactory.getOrderCode("TWO", ""));
        tCkOrders.setDeliveryId(tCkOrderdetail.getDeliveryId());
        tCkOrders.setDeptId(getLoginUser().getDeptId());
        tCkOrders.setCkType(tCkOrderdetail.getCkType());
        tCkOrders.setOrderType(tCkOrderdetail.getOrderType());
        tCkOrders.setCreateBy(operName);
        tCkOrders.setCreateTime(DateUtils.getNowDate());
    }

    private void checkData(int index, TCkOrderdetail trdata) {
        //来源单号
        if (StringUtils.isBlank(trdata.getDeliveryId())) {
            throw new RuntimeException("导入明细第" + (index + 1) + "条来源单号为空");
        }
        if (StringUtils.isBlank(trdata.getGoodsId())) {
            throw new RuntimeException("导入明细第" + (index + 1) + "条物料编码为空");
        }
        if (StringUtils.isBlank(trdata.getGoodsName())) {
            throw new RuntimeException("导入明细第" + (index + 1) + "条物料名称为空");
        }
        if (StringUtils.isBlank(trdata.getUnit())) {
            throw new RuntimeException("导入明细第" + (index + 1) + "条物料单位为空");
        }

        if (trdata.getShelvesNum() == null) {
            throw new RuntimeException("导入明细第" + (index + 1) + "条出库数量为空");
        }

    }

    @Override
    @DataScope(deptAlias = "a")
    public List<TCkOrders> exportTCkOrdersList(TCkOrders tCkOrders) {
        return tCkOrdersMapper.exportTCkOrdersList(tCkOrders);
    }

    @Override
    public Map<String, String> sendOrderNotice(TCkOrders update) {

        Map<String, String> resultMap = new HashMap<>();

        // 获取通知单信息
        TCkOrders tCkOrders = tCkOrdersMapper.selectTCkOrdersById(update.getId());

        if (ObjectUtils.isEmpty(tCkOrders)) {
            resultMap.put("error", "待发送消息的出库通知单不存在");
            return resultMap;
        }

        if (tCkOrders.getTckOrderdetailList() == null || tCkOrders.getTckOrderdetailList().isEmpty()) {
            resultMap.put("error", "待发送消息的出库通知单没有物料明细数据");
            return resultMap;
        }

        if (!"1".equals(tCkOrders.getIsAudit())) {
            resultMap.put("error", "出库通知单未审核完成,不能发送到手持设备");
            return resultMap;
        }

        // 发送呼叫任务
        TCallNoticeOrder tCallNotice = new TCallNoticeOrder();
        // 通知单编号
        tCallNotice.setTaskId(tCkOrders.getOrderId());
        // 任务类型 1:通知单出库
        tCallNotice.setTaskType("1");
        // 状态
        tCallNotice.setStatus("0");
        // 创建者
        tCallNotice.setCreateBy(update.getCreateBy());
        tCallNotice.setCreateTime(new Date());
        tCallNotice.setUpdateBy(update.getCreateBy());
        tCallNotice.setUpdateTime(new Date());

        // 0:正常任务
        tCallNotice.setFictitious("0");
        // 来源单号
        tCallNotice.setDeliveryId(tCkOrders.getDeliveryId());
        // 部门ID
        tCallNotice.setDeptId(update.getDeptId());
        // 订单类型
        String ckType = sysDictDataMapper.selectDictLabel("outbound_type", tCkOrders.getCkType());
        tCallNotice.setOrderType(ckType);
        tNoticeOrderService.sendNotice(tCallNotice);

        resultMap.put("success", "消息发送成功");
        resultMap.put("error", "");
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, String> handAddGoodsTab(TCkOrders orders) {
        Map<String, String> resultMap = new HashMap<>();

        /*//托盘校验
        LambdaQueryWrapper<TBasePallet> eq = new LambdaQueryWrapper<>();
        eq.eq(TBasePallet::getPalletId, orders.getCtl());
        List<TBasePallet> plcs = palletMapper.selectList(eq);
        if (plcs.isEmpty()) {
            resultMap.put("error", "托盘不存在");
            return resultMap;
        }*/

        // 获取订单明细
        List<TCkOrderdetail> list = orders.getTckOrderdetailList();
        // 设置订单基本信息
        String orderCode = OrderCodeFactory.getOrderCode("CK", "");
        orders.setId(OrderCodeFactory.getOrderCode("CK", ""));
        orders.setOrderId(generateBarcode());
        orders.setCkType("1");
        orders.setIsAudit("1");
        orders.setAuditDate(new Date());
        orders.setConfirmStatus("0");
        orders.setDeptId(getDeptId());
        orders.setCreateTime(new Date());

        // 更新出库单
        int inserted = insertTCkOrders(orders);

        if (inserted > 0) {
            List<TCkOrderdetail> orderdetails = new ArrayList();  // 移动到循环外部，以便收集所有明细
            for (TCkOrderdetail orderdetail : list) {
                LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
                // 获取库存信息
                if (orderdetail.getCtl() != null && !orderdetail.getCtl().isEmpty()) {
                    wrapper.eq(TMiStock::getGoodsId, orderdetail.getGoodsId());
                    wrapper.eq(TMiStock::getStorageId, orders.getStorageId());
                    wrapper.eq(TMiStock::getCtl, orders.getCtl());
                    wrapper.eq(TMiStock::getStatus, "0");
                    wrapper.eq(TMiStock::getIsFreeze, "0");
                } else {
                    wrapper.eq(TMiStock::getGoodsId, orderdetail.getGoodsId());
                    wrapper.eq(TMiStock::getStorageId, orders.getStorageId());
                }

                List<TMiStock> tMiStocks = tMiStockMapper.selectList(wrapper);


                if (tMiStocks.isEmpty()) {
                    resultMap.put("error", "当前仓库该物料" + orderdetail.getGoodsName() + "暂无库存");
                    return resultMap;
                }


                TMiStock mergedStock = tMiStocks.get(0);
                BigDecimal shelvesNum = mergedStock.getShelvesNum();

                for (int i = 1; i < tMiStocks.size(); i++) {
                    shelvesNum = shelvesNum.add(tMiStocks.get(i).getShelvesNum());

                }
                mergedStock.setShelvesNum(shelvesNum);
                // 设置明细表基本信息
                orderdetail.setOrderId(orders.getId());
                orderdetail.setId(OrderCodeFactory.getOrderCode("CK", ""));
                orderdetail.setStockNum(mergedStock.getShelvesNum());
                orderdetail.setStorageId(mergedStock.getStorageId());
                orderdetail.setStorageShortName(mergedStock.getStorageShortName());
                orderdetail.setLocationId(mergedStock.getLocationId());
                orderdetail.setShelvesNum(orders.getSum());
                orderdetail.setGoodsNum(orders.getSum());
                orderdetail.setPickNum(BigDecimal.valueOf(0.0));

                orderdetails.add(orderdetail);  // 添加到列表中
                orders.setTckOrderdetailList(orderdetails);

            }
            List<TCkOrderdetail> tckOrderdetailList = orders.getTckOrderdetailList();
            int totalInserted = 0;
            for (TCkOrderdetail tCkOrderdetail : tckOrderdetailList) {
                tCkOrderdetail.setPickNum(BigDecimal.valueOf(0.000));
                int insert1 = tCkOrderdetailMapper.insert(tCkOrderdetail);
/*
                int insert1 = tCkOrderdetailMapper.inserts(tCkOrderdetail);
*/
                totalInserted += insert1;
            }

            if (totalInserted == tckOrderdetailList.size()) {
                // 出库任务创建，移动到循环外部
                int i = confirmOut(orders);
                if (i < 1) {
                    resultMap.put("error", "出库失败请联系管理员");
                    return resultMap;
                }
            }
        }
        resultMap.put("success", "出库任务成功");
        return resultMap;
    }


    HashSet<String> usedBarcodes = new HashSet<>(); // 存储已生成的条形码以避免重复

    public String generateBarcode() {
        Random random = new Random();
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String numbers = "0123456789";
        StringBuilder barcode;

        do {
            barcode = new StringBuilder();
            // 添加两个随机字母
            for (int i = 0; i < 2; i++) {
                barcode.append(chars.charAt(random.nextInt(chars.length())));
            }
            // 添加四个随机数字
            for (int i = 0; i < 4; i++) {
                barcode.append(numbers.charAt(random.nextInt(numbers.length())));
            }
        } while (usedBarcodes.contains(barcode.toString())); // 确保不重复

        usedBarcodes.add(barcode.toString()); // 添加到已使用集合
        return barcode.toString();
    }

    /**
     * 任务分配
     *
     * @param tCkOrders
     * @return
     */

    @Override
    public AjaxResult send(TCkOrders tCkOrders) {
        List<TCkOrderdetail> list = tCkOrders.getTckOrderdetailList();

        // 过滤出符合条件的订单详情
        List<TCkOrderdetail> filteredList = list.stream()
                .filter(orderdetail -> {
                    String isAgv = baseStorageService.getIsAgvByStorageId(orderdetail.getStorageId());
                    return "1".equals(isAgv);
                })
                .collect(Collectors.toList());

        TCkOrders orders = new TCkOrders();
        BeanUtils.copyProperties(tCkOrders, orders);
        orders.setTckOrderdetailList(filteredList);

        for (TCkOrderdetail ckOrderdetail : filteredList) {
            LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TMiStock::getGoodsId, ckOrderdetail.getGoodsId());
            wrapper.eq(TMiStock::getStorageId, ckOrderdetail.getStorageId());
            wrapper.eq(TMiStock::getCtl, ckOrderdetail.getCtl());
            wrapper.eq(TMiStock::getStatus, "0");
            wrapper.eq(TMiStock::getIsFreeze, "0");
            List<TMiStock> tMiStocks = tMiStockMapper.selectList(wrapper);
            if (tMiStocks.isEmpty()) {
                return AjaxResult.error(ckOrderdetail.getGoodsName() + "已冻结不能出库,请检查物料列表数据状态为非冻结状态");
            }
        }

        Map<String, String> map = sendIwms(orders);

        if (filteredList.size() == tCkOrders.getTckOrderdetailList().size()) {
            if (map.containsKey("error")) {
                return AjaxResult.error(map.get("error"));
            } else {
                return AjaxResult.success("推送成功");
            }
        }

        List<TCkOrderdetail> pk = list.stream()
                .filter(orderdetail -> {
                    String isAgv = baseStorageService.getIsAgvByStorageId(orderdetail.getStorageId());
                    return !"1".equals(isAgv);
                })
                .collect(Collectors.toList());

        tCkOrders.setTckOrderdetailList(pk);
        confirmOut(tCkOrders);

        return AjaxResult.success("成功");
    }


    /**
     * 创建调拨单据
     * @param tCkOrders
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int install(TCkOrdersVo tCkOrders) {
        String id = OrderCodeFactory.getOrderCode("", "");
        // 1. 创建并验证出库单
        TCkOrders ckOrders = Optional.of(new TCkOrders())
                .map(order -> {
                    order.setId(id);
                    order.setOrderId(OrderCodeFactory.getOrderCode("CK", ""));
                    order.setApplicant(SecurityUtils.getUserNick());
                    order.setRecordPerson(SecurityUtils.getUserNick());
                    order.setDeptId(getDeptId());
                    order.setRecordDate(new Date());
                    order.setOrderType("3");
                    order.setCkType("3");
                    order.setDeliveryId(generateUniqueId());
                    return order;
                })
                .filter(order -> {
                    boolean exists = tCkOrdersMapper.selectList(
                            new LambdaQueryWrapper<TCkOrders>()
                                    .eq(TCkOrders::getDeliveryId, order.getDeliveryId())
                    ).isEmpty();
                    if (!exists) {
                        throw new RuntimeException("来源单号已存在，请修改后再提交！");
                    }
                    return true;
                })
                .filter(order -> {
                    int rows = tCkOrdersMapper.insertTCkOrders(order);
                    if (rows < 0) {
                        throw new RuntimeException("入库通知单新增失败");
                    }
                    return true;
                })
                .orElseThrow(() -> new RuntimeException("创建出库单失败"));

        // 2. 处理订单明细
        tCkOrders.getData().stream()
                .map(e -> {
                    TCkOrderdetail detail = new TCkOrderdetail();
                    detail.setId(OrderCodeFactory.getOrderCode("CKTM", ""));
                    detail.setOrderId(ckOrders.getId());
                    detail.setBusinessId("RK" + generateReqCode());
                    detail.setGoodsId(e.getGoodsId());
                    detail.setGoodsName(e.getGoodsName());
                    detail.setSpecification(e.getSpecification());
                    detail.setUnit(e.getUnit());
                    detail.setStorageId(e.getStorageId());
                    detail.setCtl(e.getCtl());
                    detail.setGoodsNum(e.getTransferQuantity());
                    detail.setPrice(new BigDecimal(e.getPrice()).setScale(2, RoundingMode.HALF_UP));
                    detail.setShelvesNum(e.getTransferQuantity());
                    detail.setConfirmStatus("0");
                    detail.setStockNum(e.getShelvesNum());
                    detail.setStorageShortName(Optional.ofNullable(storageMapper.getName(e.getStorageId()))
                            .map(TBaseStorage::getStorageName)
                            .orElse(""));
                    detail.setCreateBy(SecurityUtils.getUserNick());
                    detail.setLocationId(e.getLocationId());
                    detail.setUpdateTime(DateUtils.getNowDate());
                    detail.setCreateTime(DateUtils.getNowDate());
                    return detail;
                })
                .forEach(tCkOrderdetailMapper::insert);

        // 3. 创建入库通知单
        String RK = OrderCodeFactory.getOrderCode("", "");
        TRkWareNotice wareNotice = Optional.of(new TRkWareNotice())
                .map(notice -> {
                    notice.setDeliveryId(generateUniqueId());
                    notice.setReceivingStatus("0");
                    notice.setStatus("0");
                    notice.setStorageMode("4");
                    notice.setApplicant(SecurityUtils.getUserNick());
                    notice.setDeptId(getDeptId());
                    notice.setId(RK);
                    notice.setNoticeId(OrderCodeFactory.getOrderCode("TWO", ""));
                    notice.setCreateBy(getUsername());
                    notice.setCreateTime(DateUtils.getNowDate());
                    return notice;
                })
                .filter(notice -> {
                    int cnt = rkWareNoticeMapper.selectTRkWareNoticeByOrginalId(notice.getDeliveryId());
                    if (cnt > 0) {
                        throw new RuntimeException("来源单号重复");
                    }
                    return true;
                })
                .filter(notice -> {
                    int row = rkWareNoticeMapper.insertTRkWareNotice(notice);
                    if (row <= 0) {
                        throw new RuntimeException("入库通知单创建失败");
                    }
                    return true;
                })
                .orElseThrow(() -> new RuntimeException("创建入库通知单失败"));

        // 4. 处理通知单明细
        List<TRkWareNoticeTab> iRkWareNoticeTabs = new ArrayList<TRkWareNoticeTab>();
        tCkOrders.getData().stream()
                .map(e -> {
                    TRkWareNoticeTab tab = new TRkWareNoticeTab();
                    tab.setNoticeId(RK);
                    tab.setId(OrderCodeFactory.getOrderCode("TRMX", ""));
                    tab.setSalesOrderNumber(OrderCodeFactory.getOrderCode("DBRK", ""));
                    tab.setGoodsId(e.getGoodsId());
                    tab.setGoodsName(e.getGoodsName());
                    tab.setUnit(e.getUnit());
                    tab.setStorageId(tCkOrders.getTargetStorageId());
                    tab.setSpecification(e.getSpecification());
                    tab.setPrice(new BigDecimal(e.getPrice()).setScale(2, RoundingMode.HALF_UP));
                    tab.setArraMount(e.getTransferQuantity());
                    tab.setReceiver("0");
                    tab.setInStatus("0");
                    tab.setCtl(e.getCtl());
                    tab.setCreateBy(SecurityUtils.getUserNick());
                    tab.setUpdateBy(SecurityUtils.getUserNick());
                    tab.setCreateTime(DateUtils.getNowDate());
                    tab.setUpdateTime(DateUtils.getNowDate());
                    tab.setLevelType(e.getLevelType());
                    tab.setStorageShortName(Optional.ofNullable(storageMapper.getName(e.getStorageId()))
                            .map(TBaseStorage::getStorageName)
                            .orElse(""));
                    iRkWareNoticeTabs.add(tab);
                    return tab;
                }).collect(Collectors.toList());
        rkWareNoticeMapper.batchTRkWareNoticeTab(iRkWareNoticeTabs);

        TransferOrder order = new TransferOrder();
        order.setCreator(SecurityUtils.getUserNick());
        order.setCreationTime(DateUtils.getNowDate());
        StringBuilder transferContentBuilder = new StringBuilder();

        tCkOrders.getData().forEach(e -> {
            if (transferContentBuilder.length() > 0) {
                transferContentBuilder.append("; ");
            }

            TBaseStorage storage = storageMapper.getName(e.getStorageId());
            TBaseStorage storages = storageMapper.getName(tCkOrders.getTargetStorageId());
            transferContentBuilder.append("从-->")
                    .append(storage.getStorageName())
                    .append("调拨物料'")
                    .append(e.getGoodsName())
                    .append("'数量有")
                    .append(e.getTransferQuantity())
                    .append("个调拨到-->")
                    .append(storages.getStorageName());
        });
        order.setRkId(RK);
        order.setOrderId(id);

        order.setTransferContent(transferContentBuilder.toString());
        order.setTransferStatus("创建完成");
        transferOrderMapper.insertTransferOrder(order);



        return 1;
    }

    @Override
    public Long statisticCallShelvesNum(TCkOrderdetail tCkOrderdetail) {
        //1. 首先查询已审核
        Long aLong = tCkOrdersMapper.queryTotalCallShelvesNum(tCkOrderdetail);
        if(aLong == null){
            aLong = 0L;
        }
        return aLong;
    }


    public static String generateUniqueId() {
        String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        long currentTimeMillis = System.currentTimeMillis();
        String uniqueId = Long.toString(currentTimeMillis, 36).toUpperCase();

        // 获取当前时间
        java.util.Date date = new java.util.Date();
        String hours = String.format("%02d", date.getHours());
        String minutes = String.format("%02d", date.getMinutes());
        String seconds = String.format("%02d", date.getSeconds());

        String timeString = hours + minutes + seconds;

        // 生成随机字母
        Random random = new Random();
        char randomLetter = letters.charAt(random.nextInt(letters.length()));

        return uniqueId + timeString + randomLetter;
    }


    /**
     * 推出库数据
     *
     * @param update
     * @return
     */
//    @Log(title = "推送数据出库")
    public Map<String, String> sendIwms(TCkOrders update) {
        logger.info("推送数据出库====》》》》》");
        Map<String, String> resultMap = new HashMap<>();
        TCkOrders tCkOrders = tCkOrdersMapper.selectTCkOrdersById(update.getId());
        if (tCkOrders!=null) {
            BeanUtils.copyProperties(tCkOrders, update);
        }
        List<TCkOrderdetail> list = update.getTckOrderdetailList();

        List<TCkOrderdetail> fjq = list.stream()
                .filter(orderdetail -> {
                    String isAgv = baseStorageService.getIsAgvByStorageId(orderdetail.getStorageId());
                    return "1".equals(isAgv);
                })
                .collect(Collectors.toList());

        if (fjq.isEmpty()){
             resultMap.put("error", "暂无数据推送");
        }

        List<Map<String, Object>> allDataObjects = new ArrayList<>();
        String reqCode = generateReqCode();
        BigDecimal goodsNum = null;
        for (TCkOrderdetail tCkOrderdetail : fjq) {
            goodsNum = tCkOrderdetail.getGoodsNum();
            LambdaQueryWrapper<TMiStock> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TMiStock::getGoodsId, tCkOrderdetail.getGoodsId());
            queryWrapper.eq(TMiStock::getShelvesNum, tCkOrderdetail.getStockNum());
            queryWrapper.eq(TMiStock::getGoodsName, tCkOrderdetail.getGoodsName());
            queryWrapper.eq(TMiStock::getCtl, tCkOrderdetail.getCtl());
            queryWrapper.eq(TMiStock::getStorageId, tCkOrderdetail.getStorageId());
            List<TMiStock> tMiStocks = tMiStockMapper.selectList(queryWrapper);
            if (CollectionUtils.isEmpty(tMiStocks)) {
                resultMap.put("error", "库存不存在");
                continue; // Skip this iteration and continue with the next
            }
            TMiStock tMiStock = tMiStocks.get(0);
            Map<String, Object> dataObject = createDataObject(tCkOrderdetail, tMiStock, update);
            allDataObjects.add(dataObject);
        }

        if (!allDataObjects.isEmpty()) {
            sendAllDataObjects(allDataObjects, reqCode, resultMap, update, goodsNum);
        } else {
            resultMap.put("error", "没有有效的订单明细数据发送");
        }
        return resultMap;
    }


    private Map<String, Object> createDataObject(TCkOrderdetail tCkOrderdetail, TMiStock tMiStock, TCkOrders update) {
        Map<String, Object> dataObject = new HashMap<>();
        dataObject.put("operType", "A");
        dataObject.put("orderType", "50");
        dataObject.put("orderNum", update.getId());
        dataObject.put("orderItem", tCkOrderdetail.getId());
        dataObject.put("orderKeyThird", tCkOrderdetail.getBusinessId());
        if (tMiStock.getStorageId().startsWith("FJQR")) {
            dataObject.put("whCode", "RZ01");
        } else {
            dataObject.put("whCode", tMiStock.getStorageId());
        }
        dataObject.put("ownerCode", "8000");
        BigDecimal goodsNum = tCkOrderdetail.getGoodsNum();
        dataObject.put("matCode", tCkOrderdetail.getGoodsId());
        dataObject.put("matQty", goodsNum);
        dataObject.put("traceCode", tMiStock.getCtl());
        dataObject.put("createUser", tCkOrderdetail.getApplicant());
        if (tMiStock.getCtl().startsWith("A1")) {
            dataObject.put("outOrderStr2", "KQTRAY");
            dataObject.put("batchAttr07", "1");
        } else {
            dataObject.put("outOrderStr2", "KQ2LBOX");
            dataObject.put("batchAttr07", "2");
        }
        return dataObject;
    }


    private void sendAllDataObjects(List<Map<String, Object>> allDataObjects, String reqCode, Map<String, String> resultMap, TCkOrders update, BigDecimal bigDecimal) {
        final String url = "https://172.18.29.101/wms/api/RestJsonService/pushOutOrder";
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> requestData = new HashMap<>();
        requestData.put("reqCode", reqCode);
        requestData.put("data", allDataObjects);
        String requestBody = "";
        //正式注释
        try {
            requestBody = objectMapper.writeValueAsString(requestData);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        try (CloseableHttpClient httpClient = createHttpClient()) {

            //测试注释
            /*if ("成功".equals("成功")) {
                resultMap.put("success", "消息发送成功");
                List<TCkOrderdetail> list = update.getTckOrderdetailList();
                for (TCkOrderdetail ckOrderdetail : list) {
                    ckOrderdetail.setTrNum(ckOrderdetail.getGoodsNum());
                    //修改订单明细
                    ckOrderdetail.setPickNum(bigDecimal);
                    ckOrderdetail.setCkType("1");
                    tCkOrderdetailMapper.updateById(ckOrderdetail);
                }
            } else {
                resultMap.put("error", "测试");
            }*/
            //测试注释下面的用上面的
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            httpPost.setEntity(new StringEntity(requestBody));
            HttpResponse response = httpClient.execute(httpPost);
            String responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
            JsonNode responseJson = objectMapper.readTree(responseString);
            String message = responseJson.get("message").asText();
            if ("成功".equals(message)) {
                resultMap.put("success", "消息发送成功");
                List<TCkOrderdetail> list = update.getTckOrderdetailList();
                for (TCkOrderdetail ckOrderdetail : list) {
                    ckOrderdetail.setTrNum(ckOrderdetail.getGoodsNum());
                    //修改订单明细
                    ckOrderdetail.setPickNum(bigDecimal);
                    ckOrderdetail.setCkType("1");
                    tCkOrderdetailMapper.updateById(ckOrderdetail);
                }
            } else {
                resultMap.put("error", message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String generateReqCode() {
        String hexChars = "0123456789abcdef";
        int len = 20;
        StringBuilder sb = new StringBuilder(len);
        SecureRandom random = new SecureRandom();
        for (int i = 0; i < len; i++) {
            int index = random.nextInt(hexChars.length());
            sb.append(hexChars.charAt(index));
        }
        return sb.toString();
    }

    private SSLContext createTrustAllSslContext() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }


                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new SecureRandom());
        return sslContext;
    }


    private CloseableHttpClient createHttpClient() throws Exception {
        return HttpClients.custom()
                .setSslcontext(createTrustAllSslContext())
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
    }


}
