package com.zm.order.tool.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
import com.github.dozermapper.core.Mapper;
import com.google.common.collect.Lists;
import com.zm.order.tool.server.component.ShardingKeyGenerator;
import com.zm.order.tool.server.constants.*;
import com.zm.order.tool.server.cy.WmOrderCommentStarsDao;
import com.zm.order.tool.server.cy.WmOrderNewCommentsDao;
import com.zm.order.tool.server.cymarketing.MsPointsMallLogsDao;
import com.zm.order.tool.server.dao.*;
import com.zm.order.tool.server.design.ZmStoreConfigProfileDao;
import com.zm.order.tool.server.design.ZmStorePagesDao;
import com.zm.order.tool.server.dto.SearchOrderDTO;
import com.zm.order.tool.server.engine.*;
import com.zm.order.tool.server.manager.*;
import com.zm.order.tool.server.model.*;
import com.zm.order.tool.server.newdatasource.NewDataSourceOrderDao;
import com.zm.order.tool.server.newdatasource.NewDataSourceRefundDao;
import com.zm.order.tool.server.query.*;
import com.zm.order.tool.server.request.DesignRequest;
import com.zm.order.tool.server.request.OrderDataReviseRequest;
import com.zm.order.tool.server.service.DataService;
import com.zm.order.tool.server.stream.convert.OrderStreamConverter;
import com.zm.order.tool.server.stream.convert.RefundStreamConverter;
import com.zm.order.tool.server.tempdb.*;
import com.zm.order.tool.server.utils.DateUtils;
import com.zm.util.dto.Result;
import org.apache.lucene.util.NamedThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author nianchang
 * @ClassName DataServiceImpl
 * @date 2021/06/15 11:37 上午
 */
@Service
@SuppressWarnings("all")
public class DataServiceImpl implements DataService, InitializingBean {

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

    @Value("${new.sharding.db.size}")
    private int dbSize;

    @Value("${new.sharding.tb.size}")
    private int tbSize;

    private ExecutorService executorService;

    @Autowired
    private RedisManager redisManager;

    private BlockingQueue workQueue;

    @Autowired
    private ZmStorePagesDao zmStorePagesDao;

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private OrderDiscountDao orderDiscountDao;

    @Autowired
    private RefundDao refundDao;

    @Autowired
    private OrderIndexDao orderIndexDao;

    @Autowired
    private OrderItemDao orderItemDao;

    @Autowired
    private ShardingKeyGenerator keyGenerator;

    @Autowired
    private PerformanceSelfTakeDao performanceSelfTakeDao;

    @Autowired
    private CommonManager commonManager;

    @Autowired
    private SearchManager searchManager;

    @Autowired
    private Mapper mapper;

    @Autowired
    private OrderCommentDao commentDao;

    @Autowired
    private OrderCommentDetailsDao commentDetailsDao;

    @Autowired
    private RecommendItemDao recommendItemDao;

    @Autowired
    private WmOrderNewCommentsDao newCommentsDao;

    @Autowired
    private WmOrderCommentStarsDao commentStarsDao;

    @Autowired
    private AsyncMessageManager messageManager;

    @Autowired
    private OrderDiscountDao discountDao;

    @Autowired
    private RefundItemDao refundItemDao;

    @Autowired
    private OrderAddrDao orderAddrDao;

    @Autowired
    private OrderPayDetailsDao payDetailsDao;

    @Autowired
    private IdMapDao idMapDao;

    @Autowired
    private IdOrderNoDao idOrderNoDao;

    private static List<Integer> storeIdList = new ArrayList<>();
    @Autowired
    private ZmStoreConfigProfileDao configProfileDao;

    @Autowired
    private UserIdRoutingDao routingDao;

    @Autowired
    private OrderIdUserDao orderIdUserDao;

    static {
        storeIdList.add(206082);
        storeIdList.add(203899);
        storeIdList.add(50757);
        storeIdList.add(48433);
        storeIdList.add(42603);
    }


    /**
     * 多线程配置
     */
    @Override
    public void afterPropertiesSet() {
        int coreSize = Runtime.getRuntime().availableProcessors();
        workQueue = new ArrayBlockingQueue(256);
        executorService = new ThreadPoolExecutor(10, 10, 1,
                TimeUnit.MINUTES, workQueue, new NamedThreadFactory("order-data-sync"),
                new ThreadPoolExecutor.AbortPolicy());
    }

    // TODO
    @Override
    public Result design() {
        for (Integer storeId : storeIdList) {
            List<ZmStorePages> zmStorePagesList = zmStorePagesDao.selectOne(storeId);
            for (ZmStorePages zmStorePages : zmStorePagesList) {
                String config = zmStorePages.getConfig();
                if (!StringUtils.isEmpty(config)) {
                    String newConfig = parseConfig(config);
                    updateConfig(zmStorePages, newConfig);
                }
            }
        }
        return Result.successNullData();
    }

    @Override
    public Result designList(OrderDataReviseRequest request) {
        Result result = new Result();
        List<ZmStoreConfigProfile> zmStorePagesList = configProfileDao.selectList(request.getSellerId().intValue());
        result.setStatus(true);
        result.setData(zmStorePagesList);
        return result;
    }

    @Override
    public void updateDesign(List<DesignRequest> list) {
        for (DesignRequest design : list) {
            List<Map> newMapList = new ArrayList<>();
            Map<String, Object> configMap = design.getConfigMap();
            if (!org.springframework.util.StringUtils.isEmpty(configMap.get("personal_center"))) {
                String personalCenter = configMap.get("personal_center").toString();
                List<Map> mapList = JSON.parseArray(personalCenter, Map.class);
                for (Map map : mapList) {
                    String newConfig = parseConfig(JSON.toJSONString(map));
                    newMapList.add(JSON.parseObject(newConfig));
                }
                configMap.put("personal_center", newMapList);
            }

            if (!CollectionUtils.isEmpty(configMap)) {
                ZmStoreConfigProfile record = new ZmStoreConfigProfile();
                record.setId(design.getId());
                record.setValue(JSON.toJSONString(configMap));
                configProfileDao.update(record);
            }
        }
    }

    private void updateConfig(ZmStorePages zmStorePages, String newConfig) {
        ZmStorePages update = new ZmStorePages();
        update.setId(zmStorePages.getId());
        update.setNewConfig(newConfig);
        zmStorePagesDao.update(update);
    }

    private String parseConfig(String config) {
        List<Map<String, Object>> newPage = new ArrayList<>();
        List<Map> sourceList = JSON.parseArray(config, Map.class);
        for (Map<String, Object> baseMap : sourceList) {
            Map<String, Object> pageMap = new HashMap<>();

            if (Objects.nonNull(baseMap.get("data"))) {
                Map<String, Object> dataMap = JSON.parseObject(baseMap.get("data").toString());
                String type = dataMap.get("type").toString();
                switch (type) {
                    case "title":
                        pageMap = ParseEngine1.parse(baseMap, dataMap, "qm-text");
                        break;
                    case "banner_list":
                        pageMap = ParseEngine2.parse(baseMap, dataMap, "qm-banner");
                        break;
                    case "image_nav":
                        pageMap = ParseEngine3.parse(baseMap, dataMap, "qm-image-nav");
                        break;
                    case "customer":
                        pageMap = ParseEngine4.parse(baseMap, dataMap, "qm-customer");
                        break;
                    case "webView":
                        pageMap = ParseEngine5.parse(baseMap, dataMap, "qm-web-view");
                        break;
                    case "imageHot":
                        pageMap = ParseEngine6.parse(baseMap, dataMap, "qm-image-hot");
                        break;
                    case "myMemberInfo":
                        pageMap = ParseEngine7.parse(baseMap, dataMap, "qm-member-info");
                        break;
                    case "notice":
                        pageMap = ParseEngine8.parse(baseMap, dataMap, "qm-notice");
                        break;
                    case "video":
                        pageMap = ParseEngine9.parse(baseMap, dataMap, "qm-video");
                        break;
                    case "audio":
                        pageMap = ParseEngine10.parse(baseMap, dataMap, "qm-audio");
                        break;
                    case "map":
                        pageMap = ParseEngine11.parse(baseMap, dataMap, "qm-text");
                        break;
                    case "followWx":
                        pageMap = ParseEngine12.parse(baseMap, dataMap, "qm-follow-wx");
                        break;
                    case "white":
                        pageMap = ParseEngine13.parse(baseMap, dataMap, "qm-line");
                        break;
                    case "virtualNav":
                        pageMap = ParseEngine14.parse(baseMap, dataMap, "qm-virtual-nav");
                        break;
                    case "coupon":
                        pageMap = ParseEngine15.parse(baseMap, dataMap, "qm-cash-coupon");
                        break;
                    default:
                        break;
                }
                if (!CollectionUtils.isEmpty(pageMap)) {
                    newPage.add(pageMap);
                }
            }
        }
        return JSON.toJSONString(newPage);
    }

    @Override
    public Result updateRefundFlag() {
        int count = 0;
        RefundQuery refundQuery = buildQuery();
        try {
            List<Integer> list = Lists.newArrayList(2, 4, 5);
            for (Integer bizType : list) {
                refundQuery.setBizType(bizType);
                Long lastId = 424237643681759489L;
                for (; ; ) {
                    refundQuery.setLastId(lastId);
                    List<Refund> refundList = refundDao.selectList(refundQuery);
                    if (CollectionUtils.isEmpty(refundList)) {
                        break;
                    }
                    executeUpdateFlag(refundList);
                    count += refundList.size();
                    logger.info("updateRefundFlag count:{}条", count);
                    if (refundList.size() < 100) {
                        break;
                    }
                    lastId = refundList.get(refundList.size() - 1).getId();
                }
            }
        } catch (Exception e) {
            logger.error("[updateRefundFlag]failed！cause by:{}", e);
        }
        return Result.successNullData();
    }

    private void executeUpdateFlag(List<Refund> refundList) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size:{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                for (Refund refund : refundList) {
                    Order order = orderDao.selectByOrderNo(refund.getOrderNo(), refund.getUserId());
                    if (order != null) {
                        Order update = new Order();
                        update.setId(order.getId());
                        update.setUserId(order.getUserId());
                        update.setRefundFlag(1);
                        orderDao.update(update);
                    }
                }
            } catch (Exception e) {
                logger.error("[executeUpdateFlag]failed！cause by:{}", e);
            }
        });
    }

    private RefundQuery buildQuery() {
        RefundQuery refundQuery = new RefundQuery();
        refundQuery.setUpdatedAtStart(new Date(1609430400000L));
        refundQuery.setUpdatedAtEnd(new Date(1624982340000L));
        refundQuery.setSize(100);
//        refundQuery.setRefundNo("CY17040716102791393167");
        return refundQuery;
    }

    @Override
    public Result updateUserId() {
        int count = 0;
        try {
            for (String val : ListConst.list) {
                execute(val);
                count++;
            }
            for (String val : ListConst2.list) {
                execute(val);
                count++;
            }
            for (String val : ListConst3.list) {
                execute(val);
                count++;
            }
            for (String val : ListConst4.list) {
                execute(val);
                count++;
            }
            logger.info("updateUserId_count:{}", count);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.successNullData();
    }

    @Autowired
    private OrderStreamConverter orderStreamConverter;

    @Autowired
    private RefundStreamConverter refundStreamConverter;

    @Autowired
    private NewDataSourceOrderDao newDataSourceOrderDao;

    @Autowired
    private NewDataSourceRefundDao newDataSourceRefundDao;
    
    private void execute(String orderNo) throws IOException {
        while (workQueue.remainingCapacity() < 10) {
            logger.info("workQueue size:{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                OrderIndex index = orderIndexDao.selectOne(orderNo);
                if (index != null) {
                    Order order = orderDao.selectByOrderNo(index.getOrderNo(), index.getUserId());
                    Order newOrder = (Order) orderStreamConverter.streamIn(order);
                    newDataSourceOrderDao.replaceList(Lists.newArrayList(newOrder));
                    searchManager.indexOrder(newOrder, null);

                    List<Refund> refunds = refundDao.selectByOrderNo(newOrder.getOrderNo());
                    if (!CollectionUtils.isEmpty(refunds)) {
                        refunds.forEach(refund -> {
                            Refund newRefund = (Refund) refundStreamConverter.streamIn(refund);
                            newDataSourceRefundDao.replaceList(Lists.newArrayList(newRefund));
                        });
                    }
                }
            } catch (Exception e) {
                logger.error("[executeComment]failed！cause by:{}", e);
            }
        });

    }

    // TODO
    @Override
    public Result updateUser(OrderDataReviseRequest request) {
        // 查询数据库逻辑 -- 保留
        Assert.notNull(request.getOrderNo(), "订单号为空");
        Assert.notNull(request.getNewUserId(), "用户ID为空");
        String orderNo = request.getOrderNo();
        Long val = request.getNewUserId();
        OrderIndex orderIndex = orderIndexDao.selectOne(orderNo);
        if (orderIndex != null) {
            Order order = orderDao.selectByOrderNo(orderIndex.getOrderNo(), orderIndex.getUserId());
            if (order != null) {
                process(val, order, order.getSellerId(), order.getStoreId());
            }
        }
        return Result.successNullData();
    }

    private void process(Long val, Order order, Long sellerId, Long storeId) {
        try {
            List<InnerOrderItem> innerItemList = updateItem(val, order, sellerId);
            // 优惠
            updateDiscount(val, order, sellerId);
            // 订单
            Order newOrder = updateOrder(val, order, innerItemList, sellerId, storeId);
            // ES
            updateES(order, newOrder);
            // 地址
            updateAddress(val, order);
            // 支付明细
            updatePay(val, order);
            // 订单索引
            updateIndex(val, newOrder);
            // 退款单和退款商品
            updateRefund(val, order, sellerId, storeId);
        } catch (Exception e) {
            logger.error("PROCESS_FAILED! orderNo:{}, cause by:{}", order.getOrderNo(), e);
        }
    }

    private void updateRefund(Long val, Order order, Long sellerId, Long storeId) {
        RefundQuery query = new RefundQuery();
        query.setOrderNo(order.getOrderNo());
        List<Refund> refundList = refundDao.selectList(query);
        if (!CollectionUtils.isEmpty(refundList)) {
            for (Refund refund : refundList) {
                refundDao.updateUserId(refund.getId(), val, sellerId, storeId);
                List<RefundItem> refundItemList = refundItemDao.selectByRefundNo(refund.getRefundNo(), refund.getOrderNo());
                if (!CollectionUtils.isEmpty(refundItemList)) {
                    for (RefundItem refundItem : refundItemList) {
                        refundItemDao.updateUserId(refundItem.getId(), val, sellerId);
                    }
                }
            }
        }
    }

    private void updateIndex(Long val, Order newOrder) {
        OrderIndex orderIndex = orderIndexDao.selectOne(newOrder.getOrderNo());
        if (orderIndex == null) {
            orderIndex = new OrderIndex();
            orderIndex.setId(keyGenerator.generateSnowflakeNumKey());
            orderIndex.setOrderNo(newOrder.getOrderNo());
            orderIndex.setUserId(val);
            orderIndex.setOrderId(newOrder.getId());
            orderIndex.setBizType(newOrder.getBizType());
            orderIndexDao.insert(orderIndex);
        } else {
            orderIndex.setUserId(val);
            orderIndex.setOrderId(newOrder.getId());
            orderIndexDao.update(orderIndex);
        }
    }

    private void updatePay(Long val, Order order) {
        List<OrderPayDetails> payDetailsList = payDetailsDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
        if (!CollectionUtils.isEmpty(payDetailsList)) {
            for (OrderPayDetails payDetails : payDetailsList) {
                OrderPayDetails updatePay = mapper.map(payDetails, OrderPayDetails.class);
                updatePay.setId(keyGenerator.generateSnowflakeNumKey());
                updatePay.setUserId(val);
                payDetailsDao.insert(updatePay);
                payDetailsDao.delete(payDetails.getId(), payDetails.getUserId());
            }
        }
    }

    private void updateAddress(Long val, Order order) {
        OrderAddr orderAddr = orderAddrDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
        if (orderAddr != null) {
            OrderAddr updateAddr = mapper.map(orderAddr, OrderAddr.class);
            updateAddr.setId(keyGenerator.generateSnowflakeNumKey());
            updateAddr.setUserId(val);
            orderAddrDao.insert(updateAddr);
            orderAddrDao.delete(orderAddr.getId(), orderAddr.getUserId());
        }
    }

    private void updateES(Order order, Order newOrder) {
        try {
            searchManager.deleteOrder(order.getId(), order.getSellerId());
            searchManager.indexOrder(newOrder, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Order updateOrder(Long val, Order order, List<InnerOrderItem> innerItemList, Long sellerId, Long storeId) {
        Order newOrder = mapper.map(order, Order.class);
        newOrder.setId(keyGenerator.generateSnowflakeNumKey());
        newOrder.setUserId(val);
        newOrder.setSellerId(sellerId);
        newOrder.setStoreId(storeId);
        if (!CollectionUtils.isEmpty(innerItemList)) {
            if (innerItemList.size() > 10) {
                newOrder.setItemInfo("TL");
            } else {
                newOrder.setItemInfo(JSON.toJSONString(innerItemList));
            }
        }
        orderDao.insert(newOrder);
        orderDao.delete(order.getId(), order.getUserId(), -1);
        return newOrder;
    }

    private void updateDiscount(Long val, Order order, Long sellerId) {
        List<OrderDiscount> discountList = discountDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
        if (!CollectionUtils.isEmpty(discountList)) {
            for (OrderDiscount orderDiscount : discountList) {
                OrderDiscount updateDiscount = mapper.map(orderDiscount, OrderDiscount.class);
                updateDiscount.setId(keyGenerator.generateSnowflakeNumKey());
                updateDiscount.setUserId(val);
                updateDiscount.setSellerId(sellerId);
                discountDao.inserts(Lists.newArrayList(updateDiscount));
                discountDao.deletes(Lists.newArrayList(orderDiscount.getId()), orderDiscount.getUserId(), -1);
            }
        }
    }

    private List<InnerOrderItem> updateItem(Long val, Order order, Long sellerId) {
        List<InnerOrderItem> innerItemList = new ArrayList<>();
        List<OrderItem> itemList = orderItemDao.selectByOrderNo(order.getOrderNo(), order.getUserId());
        if (!CollectionUtils.isEmpty(itemList)) {
            List<OrderItem> newItemList = rebuildItem(itemList, val, sellerId);
            //
            for (OrderItem insert : newItemList) {
                orderItemDao.inserts(Lists.newArrayList(insert));
                innerItemList.add(mapper.map(insert, InnerOrderItem.class));
            }
            //
            for (OrderItem delete : itemList) {
                orderItemDao.deletes(Lists.newArrayList(delete.getId()), order.getUserId(), -1);
            }
        }
        return innerItemList;
    }

    /**
     * TODO
     * 重新组装套餐商品
     *
     * @param itemList
     * @return Date: 2021/10/20 4:58 下午
     */
    private List<OrderItem> rebuildItem(List<OrderItem> itemList, Long val, Long sellerId) {
        if (CollectionUtils.isEmpty(itemList)) {
            return Collections.EMPTY_LIST;
        }
        List<OrderItem> newItemList = Lists.newArrayList();
        for (OrderItem item : itemList) {
            OrderItem orderItem = mapper.map(item, OrderItem.class);
            if (Objects.equals(1, orderItem.getItemType())) {
                Map<String, Object> extraMap = orderItem.getExtraMap();
                if (extraMap == null) {
                    extraMap = new HashMap<>(1);
                }
                extraMap.put("rootSetMealItemId", orderItem.getId());
                orderItem.setExtraMap(extraMap);
            }
            orderItem.setId(keyGenerator.generateSnowflakeNumKey());
            orderItem.setUserId(val);
            orderItem.setSellerId(sellerId);
            newItemList.add(orderItem);
        }
        rebuild(newItemList);
        return newItemList;
    }

    private void rebuild(List<OrderItem> itemList) {
        for (OrderItem orderItem : itemList) {
            if (Objects.equals(2, orderItem.getItemType())) {
                find(itemList, orderItem);
            }
        }
    }

    private void find(List<OrderItem> itemList, OrderItem orderItem) {
        Long ownerId = orderItem.getOwnerId();
        for (OrderItem item : itemList) {
            if (Objects.equals(1, item.getItemType())) {
                Map<String, Object> extraMap = item.getExtraMap();
                if (Objects.nonNull(extraMap.get("rootSetMealItemId"))) {
                    Object rootSetMealItemId = extraMap.get("rootSetMealItemId");
                    if (Objects.equals(ownerId, rootSetMealItemId)) {
                        orderItem.setOwnerId(item.getId());
                    }
                }
            }
        }
    }


    private static List<Integer> sellerIdList = new ArrayList<>();

    static {
        sellerIdList.add(21884);
        sellerIdList.add(25278);
        sellerIdList.add(50477);
        sellerIdList.add(206243);
        sellerIdList.add(207731);
    }

    // TODO
    @Override
    public Result comment() {
        try {
            int count = 0;
            CyCommentQuery query = new CyCommentQuery();
            for (Integer sellerId : sellerIdList) {
                query.setSize(200);
//                query.setOrderNo("D5DD628032D8484518");
                query.setStoreId(sellerId);
                Integer lastId = null;
                for (; ; ) {
                    query.setLastId(lastId);
                    List<WmOrderNewComments> cyCommentList = newCommentsDao.selectList(query);
                    if (CollectionUtils.isEmpty(cyCommentList)) {
                        break;
                    }
                    executeComment(cyCommentList);
                    count += cyCommentList.size();
                    logger.info("cyCommentList:{}条", count);
                    if (cyCommentList.size() < 200) {
                        break;
                    }
                    lastId = cyCommentList.get(cyCommentList.size() - 1).getId();
                    List<Integer> idList = cyCommentList.stream().map(WmOrderNewComments::getId).collect(Collectors.toList());
                    logger.info("[LAST_ID_COMMENT]cyCommentList:{},lastId:{}", idList, lastId);
                }
            }
        } catch (Exception e) {
            logger.error("[comment]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    @Override
    public Result deleteComment() {
        int count = 0;
        OrderCommentQuery query = new OrderCommentQuery();
        query.setSellerId(203490L);
        query.setSize(200);
        Long lastId = null;
        for (; ; ) {
            query.setLastId(lastId);
//            List<OrderComment> commentList = commentDao.selectIdList(query);
            List<OrderCommentDetails> commentList = commentDetailsDao.selectIdList(query);
            if (CollectionUtils.isEmpty(commentList)) {
                break;
            }
            List<Long> idList = commentList.stream().map(OrderCommentDetails::getId).collect(Collectors.toList());
//            commentDao.delete(idList, 203490L);
            commentDetailsDao.delete(idList, 203490L);
            count += idList.size();
            logger.info("DELETE_COMMENT_COUNT:{}", count);
            if (idList.size() < 200) {
                break;
            }
            lastId = idList.get(idList.size() - 1);
        }
        return Result.successNullData();
    }

    private void executeComment(List<WmOrderNewComments> cyCommentList) {
        while (workQueue.remainingCapacity() < 10) {
            logger.info("workQueue size:{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                logger.info("[executeComment]...");
                for (WmOrderNewComments wmOrderNewComments : cyCommentList) {
                    List<WmOrderCommentStars> commentStarsList = commentStarsDao.selectList(wmOrderNewComments.getCommentNo());
                    OrderComment orderComment = buildComment(wmOrderNewComments, commentStarsList);
                    List<InnerCommentDetails> innerCommentDetails = new ArrayList<>();
                    List<OrderCommentDetails> commentDetailsList = buildCommentDetails(commentStarsList, innerCommentDetails, orderComment);
                    orderComment.setCommentInfo(JSON.toJSONString(innerCommentDetails));
                    commentDao.insert(orderComment);
                    if (!CollectionUtils.isEmpty(commentDetailsList)) {
                        commentDetailsDao.insertList(commentDetailsList);
                    }
                    messageManager.sendCommentCountMessage(orderComment);
                }
            } catch (Exception e) {
                logger.error("[executeComment]failed！cause by:{}", e);
            }
        });
    }

    private OrderComment buildComment(WmOrderNewComments wmOrderNewComments, List<WmOrderCommentStars> commentStarsList) {
        OrderComment orderComment = new OrderComment();
        orderComment.setBizType(5);
        orderComment.setId(keyGenerator.generateSnowflakeNumKey());
        Order order = orderDao.selectByOrderNo(wmOrderNewComments.getOrderNo(), wmOrderNewComments.getUserId());
        orderComment.setOrderNo(wmOrderNewComments.getOrderNo());
        orderComment.setUserId(wmOrderNewComments.getUserId());
        orderComment.setSellerId(Long.valueOf(wmOrderNewComments.getStoreId()));
        orderComment.setStoreId(Long.valueOf(wmOrderNewComments.getMultiStoreId()));
        orderComment.setOrderType(order != null ? order.getOrderType() : 0);
        orderComment.setBuyerRemarks(wmOrderNewComments.getContent());
        orderComment.setExistImage(0);
        if (!StringUtils.isEmpty(wmOrderNewComments.getImage()) && !Objects.equals("[]", wmOrderNewComments.getImage())) {
            orderComment.setExistImage(1);
            orderComment.setCommentImageList(Lists.newArrayList(wmOrderNewComments.getImage()));
        }
        if (Objects.nonNull(wmOrderNewComments.getCommentLevel())) {
            Integer commentLevel = wmOrderNewComments.getCommentLevel();
            switch (commentLevel) {
                case 1:
                    orderComment.setCommentType(0);
                    break;
                case 2:
                    orderComment.setCommentType(1);
                    break;
                case 3:
                    orderComment.setCommentType(2);
                    break;
                default:
                    orderComment.setCommentType(commentLevel);
            }
        }
        if (!StringUtils.isEmpty(wmOrderNewComments.getReplyContent())) {
            orderComment.setSellerReply(1);
            orderComment.setSellerReplyInfo(wmOrderNewComments.getReplyContent());
            orderComment.setReplyAt(DateUtils.next(wmOrderNewComments.getCreatedAt(), Calendar.HOUR_OF_DAY, 1));
        } else {
            orderComment.setSellerReply(0);
            orderComment.setSellerReplyInfo("");
        }
        orderComment.setHide(0);
        orderComment.setAnonymous(0);
        orderComment.setExistRecommend(0);
        orderComment.setQuality(Objects.nonNull(wmOrderNewComments.getStickStatus()) ?
                wmOrderNewComments.getStickStatus() : 0);
        for (WmOrderCommentStars wmOrderCommentStars : commentStarsList) {
            if (Objects.equals(wmOrderCommentStars.getCommentProjectType(), 5)) {
                Integer deliveryType = wmOrderCommentStars.getCommentProjectType();
                if (deliveryType > 3) {
                    orderComment.setDeliveryComment(0);
                    break;
                }
                if (deliveryType < 3) {
                    orderComment.setDeliveryComment(2);
                    break;
                }
                if (deliveryType == 3) {
                    orderComment.setDeliveryComment(1);
                    break;
                }
            }
        }
        if (Objects.isNull(orderComment.getDeliveryComment())) {
            orderComment.setDeliveryComment(0);
        }
        orderComment.setCommentAt(wmOrderNewComments.getCreatedAt());
        Map<String, Object> extraMap = orderComment.getExtraMap();
        if (CollectionUtils.isEmpty(extraMap)) {
            extraMap = new HashMap<>(1);
        }
        extraMap.put("historyCommentFlag", 1);
        orderComment.setExtraMap(extraMap);
        return orderComment;
    }

    private List<OrderCommentDetails> buildCommentDetails(List<WmOrderCommentStars> commentStarsList,
                                                          List<InnerCommentDetails> innerCommentDetails, OrderComment orderComment) {
        List<OrderCommentDetails> list = new ArrayList<>();
        for (WmOrderCommentStars wmOrderCommentStars : commentStarsList) {
            OrderCommentDetails commentDetails = new OrderCommentDetails();
            commentDetails.setId(keyGenerator.generateSnowflakeNumKey());
            commentDetails.setUserId(orderComment.getUserId());
            commentDetails.setOrderNo(orderComment.getOrderNo());
            commentDetails.setSellerId(orderComment.getSellerId());
            commentDetails.setStoreId(orderComment.getStoreId());
            Integer commentType = wmOrderCommentStars.getCommentProjectType();
            if (Objects.equals(1, commentType)) {
                commentDetails.setCommentType(2);
                commentDetails.setCommentName("口味");
            }
            if (Objects.equals(2, commentType)) {
                commentDetails.setCommentType(1);
                commentDetails.setCommentName("菜品");
            }
            if (Objects.equals(3, commentType)) {
                commentDetails.setCommentType(4);
                commentDetails.setCommentName("服务");
            }
            if (Objects.equals(4, commentType)) {
                commentDetails.setCommentType(6);
                commentDetails.setCommentName("环境");
            }
            if (Objects.equals(5, commentType)) {
                commentDetails.setCommentType(8);
                commentDetails.setCommentName("配送");
            }
            commentDetails.setCommentScore(wmOrderCommentStars.getCommentStar());
            innerCommentDetails.add(mapper.map(commentDetails, InnerCommentDetails.class));
            list.add(commentDetails);
        }
        OrderCommentDetails commentDetails = new OrderCommentDetails();
        commentDetails.setId(keyGenerator.generateSnowflakeNumKey());
        commentDetails.setUserId(orderComment.getUserId());
        commentDetails.setOrderNo(orderComment.getOrderNo());
        commentDetails.setSellerId(orderComment.getSellerId());
        commentDetails.setStoreId(orderComment.getStoreId());
        commentDetails.setCommentType(100);
        commentDetails.setCommentName("评分");
        commentDetails.setCommentScore(5);
        innerCommentDetails.add(mapper.map(commentDetails, InnerCommentDetails.class));
        list.add(commentDetails);
        return list;
    }

    @Override
    public Result updateSellerUserId(DataCorrectionRequest request) {
        int count = 0;
        final Long updateSellerId = 1001206110L;
        OrderQuery orderQuery = new OrderQuery();
        orderQuery.setSellerId(1001206110L);
        orderQuery.setSize(200);
        try {
            for (int i = 0; i < dbSize; i++) {
                for (int j = 0; j < tbSize; j++) {
                    Long lastId = null;
                    for (; ; ) {
                        orderQuery.setLastId(lastId);
                        long startAt = System.currentTimeMillis();
                        List<Long> orderIdList = commonManager.scanOrderId(orderQuery, i, j);
                        if (CollectionUtils.isEmpty(orderIdList)) {
                            break;
                        }
                        List<Order> orderList = commonManager.listOrderById(orderIdList, i, j);
                        logger.info("query_time:{}ms", System.currentTimeMillis() - startAt);
                        //
                        orderExecute0(orderList, updateSellerId);
                        //
                        count += orderIdList.size();
                        logger.info("updateSellerUserId:{}条", count);
                        if (orderIdList.size() < 200) {
                            break;
                        }
                        lastId = orderIdList.get(orderIdList.size() - 1);
                        //
                        logger.info("updateSellerUserId_lastId:{},i:{},j:{}", lastId, i, j);
                        Result<String> redisData = redisManager.get("update_Seller_UserId_key");
                        if (redisData.isStatus() && Objects.nonNull(redisData.getData())) {
                            return Result.successNullData();
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("[updateSellerUserId]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    private void orderExecute0(List<Order> orderList, final Long updateSellerId) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                for (Order order : orderList) {
                    Long newUserId = UserIDMapConst.map.get(order.getUserId());
                    if (Objects.isNull(newUserId)) {
                        logger.warn("orderExecute0_newUserId is null！orderNo:{}, userId:{}",
                                order.getOrderNo(), order.getUserId());
                        continue;
                    }
                    Long newStoreId = StoreIDMapConst.map.get(order.getStoreId());
                    if (Objects.isNull(newStoreId)) {
                        logger.warn("orderExecute0_newStoreId is null！orderNo:{}, storeId:{}",
                                order.getOrderNo(), order.getStoreId());
                        continue;
                    }
                    process(newUserId, order, updateSellerId, newStoreId);
                }
            } catch (Exception e) {
                logger.error("[orderExecute0]failed！cause by:{}", e);
            }
        });
    }

    /**
     * TODO
     * 调整线程
     *
     * @param request
     * @return Date: 2021/10/20 10:54 下午
     */
    @Override
    public Result updateSellerUserIdTemp(DataCorrectionRequest request) {
        int count = 0;
        Long lastId = null;
        try {
            for (; ; ) {
                List<IdMap> idMapList = idMapDao.selectList(lastId);
                if (CollectionUtils.isEmpty(idMapList)) {
                    break;
                }
                orderExecute1(idMapList);
                count += idMapList.size();
                logger.info("updateSellerUserIdTemp:{}条", count);
                if (idMapList.size() < 200) {
                    break;
                }
                lastId = idMapList.get(idMapList.size() - 1).getIgnoreId();
            }
        } catch (Exception e) {
            logger.error("[updateSellerUserId]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    /**
     * 从临时表找ID映射
     *
     * @param orderList
     * @param updateSellerId
     * @return Date: 2021/10/18 4:47 下午
     */
    private void orderExecute1(List<IdMap> idMapList) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                for (IdMap idMap : idMapList) {
                    OrderQuery orderQuery = new OrderQuery();
                    orderQuery.setUserId(idMap.getIgnoreId());
                    List<Order> orderList = orderDao.selectList(orderQuery);
                    if (!CollectionUtils.isEmpty(orderList)) {
                        for (Order order : orderList) {
                            process(idMap.getImportId(), order, order.getSellerId(), order.getStoreId());
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("[orderExecute1]failed！cause by:{}", e);
            }
        });
    }

    @Override
    public Result repeatID() {
        int count = 0;
        Long lastId = null;
        AtomicInteger countOrder = new AtomicInteger();
        try {
            for (; ; ) {
                List<IdMap> idMapList = idMapDao.selectList(lastId);
                if (CollectionUtils.isEmpty(idMapList)) {
                    break;
                }
                idMapList.forEach(idMap -> orderExecute2(idMap, countOrder));
                count += idMapList.size();
                logger.info("repeatID:{}条", count);
                logger.info("repeatID_AtomicInteger:{}条", countOrder);
                if (idMapList.size() < 200) {
                    break;
                }
                lastId = idMapList.get(idMapList.size() - 1).getIgnoreId();
            }
        } catch (Exception e) {
            logger.error("[repeatID]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    private void orderExecute2(IdMap idMap, AtomicInteger countOrder) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                long startAt = System.currentTimeMillis();
                OrderQuery orderQuery = new OrderQuery();
                orderQuery.setUserId(idMap.getImportId());
                List<Order> orderList = orderDao.selectList(orderQuery);
                logger.info("orderExecute2_time:{}ms", System.currentTimeMillis() - startAt);
                if (!CollectionUtils.isEmpty(orderList)) {
                    for (Order lnjOrder : orderList) {
                        Order otherOrder = scan(lnjOrder.getId(), lnjOrder.getOrderNo(), countOrder);
//                            doSave(lnjOrder, otherOrder);
                    }
                }
                logger.info("orderExecute2_time1:{}ms", System.currentTimeMillis() - startAt);
            } catch (Exception e) {
                logger.error("[orderExecute2]failed！cause by:{}", e);
            }
        });
    }


    private void orderExecute4(List<IdMap> idMapList, AtomicInteger countOrder) {
        try {
            for (IdMap idMap : idMapList) {
                OrderQuery orderQuery = new OrderQuery();
                orderQuery.setUserId(idMap.getImportId());
                List<Order> orderList = orderDao.selectList(orderQuery);
                if (!CollectionUtils.isEmpty(orderList)) {
                    for (Order lnjOrder : orderList) {
                        Order otherOrder = scan(lnjOrder.getId(), lnjOrder.getOrderNo(), countOrder);
//                            doSave(lnjOrder, otherOrder);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("[orderExecute2]failed！cause by:{}", e);
        }
    }

    @Override
    public Result resetId() {
        MapConst2.map.forEach((k, v) -> {
            OrderIndex orderIndex1 = orderIndexDao.selectOne(k);
            Order updateOrder = null;
            if (orderIndex1 != null) {
                updateOrder = orderDao.selectByOrderNo(orderIndex1.getOrderNo(), orderIndex1.getUserId());
            }

            Order insertOrder = null;
            OrderIndex orderIndex2 = orderIndexDao.selectOne(v);
            if (orderIndex2 != null) {
                insertOrder = orderDao.selectByOrderNo(orderIndex2.getOrderNo(), orderIndex2.getUserId());
            }
            try {
                doSave(updateOrder, insertOrder);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        return Result.successNullData();
    }

    @Override
    public Result repeatUpdateDeliveryId() {
        logger.info("repeatUpdateDeliveryId[start]");
        int count = 0;
        for (String key : MapConst4.map.keySet()) {
            String value = MapConst4.map.get(key);

            OrderIndex index = orderIndexDao.selectOne(key);
            if (Objects.isNull(index)) {
                continue;
            }
            Order order = orderDao.selectByOrderNo(index.getOrderNo(), index.getUserId());
            if (Objects.isNull(order)) {
                continue;
            }
            Map<String, Object> extraMap = order.getExtraMap();
            Object takeOutInfo = extraMap.get("TakeOutInfo");
            if (Objects.nonNull(takeOutInfo)) {
                String s = takeOutInfo.toString();
                Map<String, Object> extra = JSON.parseObject(s, Map.class);
                extra.put("deliveryId", value);
                extraMap.put("TakeOutInfo", extra);
                order.setExtraMap(extraMap);
                orderDao.updateFeatures(order);
            }
            count++;
        }
        logger.info("repeatUpdateDeliveryId[end], count:{}", count);

        return Result.successNullData();
    }

    @Override
    public Result queryRepeatId() {
        int count = 0;
        AtomicInteger repeatCount = new AtomicInteger();
        OrderQuery orderQuery = new OrderQuery();
        orderQuery.setSize(200);
        try {
            for (int i = 0; i < dbSize; i++) {
                for (int j = 0; j < tbSize; j++) {
                    Long lastId = 606834778133561345L;
                    for (;;) {
                        orderQuery.setLastId(lastId);
                        List<Order> orderList = commonManager.scanOrder(orderQuery, i, j);
                        if (CollectionUtils.isEmpty(orderList)) {
                            break;
                        }
                        //
                        orderExecute6(orderList, repeatCount);
                        count += orderList.size();
                        logger.info("queryRepeatId_count:{}条", count);
                        if (orderList.size() < 200) {
                            break;
                        }
                        lastId = orderList.get(orderList.size() - 1).getId();
                        logger.info("queryRepeatId_lastId,i:{},j:{},lastId:{}", i, j, lastId);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("[queryRepeatId]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    @Override
    public Result routingCheck() {
        int count = 0;
        OrderQuery orderQuery = new OrderQuery();
        orderQuery.setSize(200);
        AtomicInteger repeatCount = new AtomicInteger();
        try {
            for (int i = 0; i < dbSize; i++) {
                Long lastId = null;
                for (;;) {
                    orderQuery.setLastId(lastId);
                    List<Order> orderList = commonManager.scanOrder(orderQuery, i, 0);
                    if (CollectionUtils.isEmpty(orderList)) {
                        break;
                    }
                    orderExecute7(orderList, repeatCount, i, 0);
                    count += orderList.size();
                    logger.info("routingCheck_count:{}条", count);
                    if (orderList.size() < 200) {
                        break;
                    }
                    lastId = orderList.get(orderList.size() - 1).getId();
                    logger.info("routingCheck_lastId,i:{},j:{},lastId:{}", i, 0, lastId);
                }
            }
        } catch (Exception e) {
            logger.error("[queryRepeatId]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    @Override
    public Result setRouting(int maxLoop) {
        int loop = 0;
        int count = 0;
        Long userId = null;
        for (;;) {
            List<UserIdRouting> routingList = routingDao.selectList(userId);
            if (CollectionUtils.isEmpty(routingList)) {
                break;
            }
            orderExecute8(routingList);
            count += routingList.size();
            logger.info("setRoutingCount:{}", count);
            if (routingList.size() < 1000) {
                break;
            }
            userId = routingList.get(routingList.size() - 1).getId();
            if (loop >= maxLoop) {
                break;
            }
            loop++;
        }
        return Result.successNullData();
    }

    @Autowired
    private OrderManager orderManager;
    
    @Override
    public Result test(Order order) {
        OrderNoUser orderNoUser = new OrderNoUser();
        orderNoUser.setOrderNo("892321321");
        orderNoUser.setUserId(111L);
        orderManager.test(orderNoUser);
        return Result.successNullData();
    }

    @Override
    public Result insertIndex(Order request) {
        OrderIndex orderIndex = orderIndexDao.selectOne(request.getOrderNo());
        if (orderIndex == null) {
            Order order = orderDao.selectByOrderNo(request.getOrderNo(), request.getUserId());
            if (order != null) {
                OrderIndex orderIndex1 = new OrderIndex();
                orderIndex1.setId(keyGenerator.generateSnowflakeNumKey());
                orderIndex1.setOrderNo(order.getOrderNo());
                orderIndex1.setUserId(order.getUserId());
                orderIndex1.setOrderId(order.getId());
                orderIndex1.setBizType(order.getBizType());
                orderIndexDao.insert(orderIndex1);
            }
        }
        return Result.successNullData();
    }

    private void orderExecute8(List<UserIdRouting> routingList) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                for (UserIdRouting routing : routingList) {
                    Long userId = routing.getUserId();
                    int routingkey = userId.toString().hashCode();
                    if (routingkey < 0) {
                        routingkey = -routingkey;
                    }
                    int globalIndex = routingkey / 1024;
                    int dbIndex = routingkey % 32;
                    int tbIndex = globalIndex % 32;
//                    int dbIndex = routingkey % 32;
//                    int tbIndex = routingkey / 32 % 32;
                    routing.setDbIndex(dbIndex);
                    routing.setTbIndex(tbIndex);
                }
                routingDao.update(routingList);
            } catch (Exception e) {
                logger.error("[orderExecute8]failed！cause by:{}", e);
            }
        });
    }

    private void orderExecute7(List<Order> orderList, AtomicInteger repeatCount, int i, int j) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                for (Order order : orderList) {
                    final Long userId = order.getUserId();
                    long dbIndex, tbIndex;
                    if (SpecialAlgorithm.isForward(userId, dbSize, tbSize)) {
                        dbIndex = SpecialAlgorithm.forward(userId, dbSize);
                        tbIndex = SpecialAlgorithm.forward(userId, dbSize, tbSize);
                    } else {
                        dbIndex = RoutingAlgorithm.routeDB(userId, dbSize);
                        tbIndex = RoutingAlgorithm.routeTB(userId, dbSize, tbSize);
                    }
                    if (dbIndex != i || tbIndex != j) {
                        repeatCount.incrementAndGet();
                        logger.info("[ROUTING_CHECK_FIND]find！orderNo:{}, userId:{}", order.getOrderNo(), order.getUserId());
                    }
                }
            } catch (Exception e) {
                logger.error("[orderExecute7]failed！cause by:{}", e);
            }
        });
    }

    private void orderExecute6(List<Order> orderList, AtomicInteger repeatCount) {
        while (workQueue.remainingCapacity() < 1) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                List<Long> orderIdList = orderList.stream().map(Order::getId).collect(Collectors.toList());
                SearchOrderQuery searchOrderQuery = this.buildParam(orderIdList);

                long start1 = System.currentTimeMillis();
                final String[] includes = {"orderNo", "orderId", "userId"};
                SearchOrderDTO searchOrderDTO = searchManager.searchOrder(searchOrderQuery, includes, null, 5);
                List<BaseIndexOrder> indexOrderList = searchOrderDTO.getOrderList();
                if (CollectionUtils.isEmpty(indexOrderList)) {
                    return;
                }
                logger.info("stage1_time:{}ms", System.currentTimeMillis() - start1);

                long start2 = System.currentTimeMillis();
                Map<Long, List<BaseIndexOrder>> baseMap =
                        indexOrderList.stream().collect(Collectors.groupingBy(BaseIndexOrder::getOrderId));
                for (Order order : orderList) {
                    List<BaseIndexOrder> baseOrders = baseMap.get(order.getId());
                    if (!CollectionUtils.isEmpty(baseOrders)) {
                        BaseIndexOrder indexOrder = baseOrders.get(0);
                        if (!Objects.equals(indexOrder.getOrderNo(), order.getOrderNo())) {
                            repeatCount.incrementAndGet();
                            logger.info("[find_repeat_order]success！esOrder:{}, dbOrder:{}",
                                    indexOrder.getOrderNo(), order.getOrderNo());
                        }
                    }
                }
                logger.info("stage2_time:{}ms", System.currentTimeMillis() - start2);
                logger.info("orderExecute6_repeat:{}条", repeatCount);
            } catch (Exception e) {
                logger.error("[orderExecute4]failed！cause by:{}", e);
            }
        });
    }

    private SearchOrderQuery buildParam(List<Long> orderIdList) {
        SearchOrderQuery searchOrderQuery = new SearchOrderQuery();
        searchOrderQuery.setPageNo(1);
        searchOrderQuery.setPageSize(200);
        searchOrderQuery.setOrderIdList(orderIdList);
        return searchOrderQuery;
    }

    private void doSave(Order updateOrder, Order insertOrder) throws IOException {
        try {
            if (updateOrder != null && insertOrder != null) {
                Order update = new Order();
                update.setId(updateOrder.getId());
                update.setUserId(updateOrder.getUserId());
                update.setVersion(updateOrder.getVersion());
                orderDao.update(update);
                searchManager.indexOrder(updateOrder, null);

                long newId = keyGenerator.generateSnowflakeNumKey();
                orderDao.updateId(insertOrder.getId(), insertOrder.getUserId(), newId);
                insertOrder.setId(newId);
                searchManager.indexOrder(insertOrder, null);
                OrderIndex orderIndex = orderIndexDao.selectOne(insertOrder.getOrderNo());
                if (orderIndex != null) {
                    orderIndex.setOrderId(newId);
                    orderIndexDao.update(orderIndex);
                }
            }
        } catch (Exception e) {
            logger.error("doSave_error！lnjOrder:{}, otherOrder:{}, cause by:{}", updateOrder, insertOrder, e);
        }
    }

    private Order scan(Long orderId, String excludeOrderNo, AtomicInteger countOrder) {
        for (int i = 0; i < dbSize; i++) {
            for (int j = 0; j < tbSize; j++) {
                List<Order> orderList = commonManager.scanOrderById(orderId, i, j);
                if (CollectionUtils.isEmpty(orderList)) {
                    continue;
                }
                Order order = orderList.get(0);
                if (Objects.equals(order.getOrderNo(), excludeOrderNo)) {
                    continue;
                }
                // 找到了 重新设置一个用户ID 原数据更新一次
                countOrder.incrementAndGet();
                logger.warn("FIND_ORDER! orderId:{}, excludeOrderNo:{}, orderNo:{}",
                        orderId, excludeOrderNo, order.getOrderNo());
                return order;
            }
        }
        return null;
    }
    
    @Autowired
    private OrderNoUserDao orderNoUserDao;

    @Autowired
    private MsPointsMallLogsDao mpDao;

    @Override
    public Result integralOrder() {
        int count = 0;
        Long lastId = null;
        try {
            for (;;) {
                List<OrderNoUser> list = orderNoUserDao.selectList(lastId);
                if (CollectionUtils.isEmpty(list)) {
                    break;
                }
                list.forEach(model -> orderExecute3(model.getOrderNo(), model.getUserId()));
                if (list.size() < 200) {
                    break;
                }
                lastId = list.get(list.size() - 1).getId();
            }

        } catch (Exception e) {
            logger.error("[integralOrder]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    private void orderExecute3(String orderNo, Long userId) {
        while (workQueue.remainingCapacity() < 1) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                Order order = orderDao.selectByOrderNo(orderNo, userId);
                if (order == null) {
                    return;
                }
                MsPointsMallLogs msPointsMallLogs = mpDao.selectOne(orderNo);
                if (msPointsMallLogs == null) {
                    return;
                }
                if (!Objects.equals(2, msPointsMallLogs.getGoodsType())) {
                    return;
                }
                OrderAddr addr = buildAddr(order, msPointsMallLogs);
                Order update = buildOrderUpdate(order, msPointsMallLogs, addr);

                orderDao.update(update);
                orderAddrDao.insert(addr);
            } catch (Exception e) {
                logger.error("[orderExecute3]failed！cause by:{}", e);
            }
        });
    }

    private Order buildOrderUpdate(Order order, MsPointsMallLogs msPointsMallLogs, OrderAddr addr) {
        Order update = new Order();
        update.setId(order.getId());
        update.setUserId(order.getUserId());
        update.setOrderSubType(29);
        Integer entityStatus = msPointsMallLogs.getSendEntityStatus();
        update.setPerformanceStatus((Objects.nonNull(entityStatus) && entityStatus > 0) ? 1 : 0);

        Map<String, Object> performanceMap = new HashMap<>();
        String performanceInfo = update.getPerformanceInfo();
        if (!org.springframework.util.StringUtils.isEmpty(performanceInfo)) {
            performanceMap.putAll(JSON.parseObject(performanceInfo));
        }
        performanceMap.put("receiverMobile", msPointsMallLogs.getUserPhone());
        update.setPerformanceInfo(JSON.toJSONString(performanceMap));
        update.setAddrInfo(JSON.toJSONString(addr));
        return update;
    }

    private OrderAddr buildAddr(Order order, MsPointsMallLogs msPointsMallLogs) {
        OrderAddr addr = new OrderAddr();
        addr.setId(keyGenerator.generateSnowflakeNumKey());
        addr.setUserId(order.getUserId());
        addr.setOrderNo(order.getOrderNo());
        addr.setAcceptName(msPointsMallLogs.getSendUsername());
        addr.setSex(1);
        addr.setProvince(0);
        addr.setCity(0);
        addr.setArea(0);
        addr.setStreet(msPointsMallLogs.getSendAddress());
        addr.setLng("0");
        addr.setLat("0");
        addr.setMobile(msPointsMallLogs.getSendMobile());
        addr.setDoorNumber("");
        addr.setProvinceName("");
        addr.setCityName("");
        addr.setAreaName("");
        addr.setLabel(0);
        return addr;
    }

    @Override
    public Result repeatIDSave() {
        int count = 0;
        Long lastId = null;
        AtomicInteger countOrder = new AtomicInteger();
        try {
            for (; ; ) {
                List<IdMap> idMapList = idMapDao.selectList(lastId);
                if (CollectionUtils.isEmpty(idMapList)) {
                    break;
                }
                orderExecute5(idMapList, countOrder);
//                idMapList.forEach(idMap -> orderExecute5(idMap, countOrder));
                count += idMapList.size();
                logger.info("repeatID:{}条", count);
                logger.info("repeatID_AtomicInteger:{}条", countOrder);
                if (idMapList.size() < 200) {
                    break;
                }
                lastId = idMapList.get(idMapList.size() - 1).getIgnoreId();
            }
        } catch (Exception e) {
            logger.error("[repeatID]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }


    private void orderExecute5(List<IdMap> idMapList, AtomicInteger countOrder) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                long startAt = System.currentTimeMillis();
                OrderQuery orderQuery = new OrderQuery();
                List<Long> userIdList = idMapList.stream().map(IdMap::getImportId).collect(Collectors.toList());
                orderQuery.setUserIdList(userIdList);

                List<Order> orderList = orderDao.selectList(orderQuery);
                logger.info("orderExecute5_time:{}ms", System.currentTimeMillis() - startAt);
                if (!CollectionUtils.isEmpty(orderList)) {
                    List<IdOrderNo> idOrderNoList = new ArrayList<>(orderList.size());
                    for (Order lnjOrder : orderList) {
                        IdOrderNo idOrderNo = new IdOrderNo();
                        idOrderNo.setOrderId(lnjOrder.getId());
                        idOrderNo.setOrderNo(lnjOrder.getOrderNo());
                        idOrderNoList.add(idOrderNo);
                    }
                    //批量保存 订单号，订单ID 到临时库新表
                    if (!CollectionUtils.isEmpty(idOrderNoList)) {
                        idOrderNoDao.insertList(idOrderNoList);
                    }
                }
                logger.info("orderExecute5_time1:{}ms", System.currentTimeMillis() - startAt);
            } catch (Exception e) {
                logger.error("[orderExecute5]failed！cause by:{}", e);
            }
        });
    }


    @Override
    public Result queryOrder1() {
        int count = 0;
        int diff = 0;
        AtomicInteger countOrder = new AtomicInteger();
        try {
            for (int i = 0; i < dbSize; i++) {
                for (int j = 0; j < tbSize; j++) {
                    orderExecute6(i,j,countOrder);
                }
            }
        } catch (Exception e) {
            logger.error("[updateSellerUserId]failed！cause by:{}", e);
            return Result.failureData(ExceptionConstants.SYSTEM_ERROR);
        }
        return Result.successNullData();
    }

    private void orderExecute6(int i, int j, AtomicInteger countOrder) {
        while (workQueue.remainingCapacity() < 1) {
            logger.info("workQueue size{}", workQueue.size());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                int count = 0;
                Long lastId = null;
                for (;;) {
                    List<IdOrderNo> idOrderList = idOrderNoDao.selectList(lastId);
                    if (CollectionUtils.isEmpty(idOrderList)) {
                        break;
                    }
                    Map<Long, List<IdOrderNo>> listMap =
                            idOrderList.stream().collect(Collectors.groupingBy(IdOrderNo::getOrderId));

                    long startAt = System.currentTimeMillis();
                    List<Order> orderList = commonManager.listOrderById(Lists.newArrayList(listMap.keySet()), i, j);

                    if (!CollectionUtils.isEmpty(orderList)) {
                        for (Order order : orderList) {
                            List<IdOrderNo> idOrderNos = listMap.get(order.getId());
                            if (!CollectionUtils.isEmpty(idOrderNos)) {
                                IdOrderNo idOrderNo = idOrderNos.get(0);
                                if (!Objects.equals(idOrderNo.getOrderNo(), order.getOrderNo())) {
                                    countOrder.incrementAndGet();
                                    logger.info("diff_order!oldOrderNo:{},newOrderNo:{},diffCount:{}条,i:{},j:{}",
                                            idOrderNo.getOrderNo(), order.getOrderNo(), countOrder,i,j);
                                }
                            }
                        }
                    }
                    count += orderList.size();
                    logger.info("queryOrder1:i:{}, j:{}, {}条", i, j, count);
                    if (idOrderList.size() < 1000) {
                        break;
                    }
                    lastId = idOrderList.get(idOrderList.size() - 1).getOrderId();
                }
            } catch (Exception e) {
                logger.error("[orderExecute5]failed！cause by:{}", e);
            }
        });
    }

    private void orderExecute7(int i, int j, AtomicInteger countOrder) {
            try {
                int count = 0;
                Long lastId = null;
                for (;;) {
                    IdOrderNo idOrderNo1 = new IdOrderNo();
                    idOrderNo1.setOrderId(657722967521755137L);
                    idOrderNo1.setOrderNo("D5F4F32F1F02583731");
                    List<IdOrderNo> idOrderList = Lists.newArrayList(idOrderNo1);
                    if (CollectionUtils.isEmpty(idOrderList)) {
                        break;
                    }
                    Map<Long, List<IdOrderNo>> listMap =
                            idOrderList.stream().collect(Collectors.groupingBy(IdOrderNo::getOrderId));

                    long startAt = System.currentTimeMillis();
                    List<Order> orderList = commonManager.listOrderById(Lists.newArrayList(listMap.keySet()), i, j);

                    if (!CollectionUtils.isEmpty(orderList)) {
                        for (Order order : orderList) {
                            List<IdOrderNo> idOrderNos = listMap.get(order.getId());
                            if (!CollectionUtils.isEmpty(idOrderNos)) {
                                IdOrderNo idOrderNo = idOrderNos.get(0);
                                if (!Objects.equals(idOrderNo.getOrderNo(), order.getOrderNo())) {
                                    countOrder.incrementAndGet();
                                    logger.info("diff_order!oldOrderNo:{},newOrderNo:{},diffCount:{}条,i:{},j:{}",
                                            idOrderNo.getOrderNo(), order.getOrderNo(), countOrder,i,j);
                                }
                            }
                        }
                    }
                    count += orderList.size();
                    logger.info("queryOrder1:i:{}, j:{}, {}条", i, j, count);
                    if (idOrderList.size() < 1000) {
                        break;
                    }
                    lastId = idOrderList.get(idOrderList.size() - 1).getOrderId();
                }
            } catch (Exception e) {
                logger.error("[orderExecute5]failed！cause by:{}", e);
            }
    }

    @Override
    public void orderMerge(){
        List<IdMap> idMapList = idMapDao.selectList(0L);
        int count = 0;
        for (IdMap idMap : idMapList) {
            OrderQuery orderQuery = new OrderQuery();
            orderQuery.setUserId(idMap.getIgnoreId());
            List<Order> orderList = orderDao.selectList(orderQuery);
            count += orderList.size();
            if (!CollectionUtils.isEmpty(orderList)) {
                for (Order order : orderList) {
                    process1(idMap.getImportId(), order, order.getSellerId(), order.getStoreId());
                }
            }
            logger.info("orderMerge_count:{}条", count);
        }
    }


    private void process1(Long val, Order order, Long sellerId, Long storeId) {
        try {
            List<InnerOrderItem> innerItemList = updateItem(val, order, sellerId);
            // 优惠
            updateDiscount(val, order, sellerId);
            // 订单
            Order newOrder = updateOrder(val, order, innerItemList, sellerId, storeId);
            // ES
            updateES(order, newOrder);
            // 地址
            updateAddress(val, order);
            // 提货信息表
            updateTake(val, order);
            // 订单索引
            updateIndex(val, newOrder);
            // 退款单和退款商品
            updateRefund(val, order, sellerId, storeId);
        } catch (Exception e) {
            logger.error("PROCESS_FAILED! orderNo:{}, cause by:{}", order.getOrderNo(), e);
        }
    }

    private void updateTake(Long val, Order order) {
        PerformanceSelfTake take = performanceSelfTakeDao.selectOne(order.getOrderNo(), order.getUserId());
        if (take != null) {
            PerformanceSelfTake updateTake = mapper.map(take, PerformanceSelfTake.class);
            updateTake.setId(keyGenerator.generateSnowflakeNumKey());
            updateTake.setUserId(val);
            performanceSelfTakeDao.insert(updateTake);
            performanceSelfTakeDao.delete(take.getId(), take.getUserId());
        }
    }

    @Override
    public void updateDiscountTime(){
        OrderDiscountQuery query = new OrderDiscountQuery();
        int size = 1000;
        query.setSize(size);
        //2022-04-26 22:00:00
        query.setUpdatedAtStart(new Date(1650981600000L));
        Long count = 0L;
        for (int i = 0; i < dbSize; i++) {
            for (int j = 0; j < tbSize; j++) {
                Long lastId = null;
                for (; ; ) {
                    query.setLastId(lastId);
                    long startAt = System.currentTimeMillis();
                    List<Long> discountIdList = commonManager.scanOrderDiscountId(query, i, j);
                    logger.info("updateDiscountTime, i:{},j:{}", i, j);
                    if (CollectionUtils.isEmpty(discountIdList)) {
                        break;
                    }
                    executeUpdateDisountUpdatedAt(discountIdList, i, j);
                    count += discountIdList.size();
                    logger.info("updateDiscountTime:count:{}条, i:{},j:{}", count, i, j);
                    if (discountIdList.size() < size) {
                        break;
                    }
                    lastId = discountIdList.get(discountIdList.size() - 1);
                    logger.info("updateDiscountTime_lastId:{},i:{},j:{}", lastId, i, j);
                }
            }
        }
    }

    private void executeUpdateDisountUpdatedAt(List<Long> discountIdList, int i, int j) {
        while (workQueue.remainingCapacity() < 20) {
            logger.info("workQueue size:{}", workQueue.size());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.submit(() -> {
            try {
                commonManager.updateOrderDiscountById(discountIdList, i, j);
            } catch (Exception e) {
                logger.error("[executeUpdateDisountUpdatedAt]failed！cause by:{}", e);
            }
        });
    }

    @Override
    public void juiceOrder() {

    }
}









