package com.liquidnet.service.platform.service.impl.kylin;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.common.cache.redisson.util.RedisLockUtil;
import com.liquidnet.common.mq.constant.MQConst;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.OrderCloseMapping;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dao.OrderScriptDto;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.entity.KylinOrderTicketRelations;
import com.liquidnet.service.kylin.entity.KylinOrderTicketStatus;
import com.liquidnet.service.kylin.entity.KylinOrderTickets;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketRelationsMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketStatusMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import com.liquidnet.service.kylin.service.IKylinOrderTicketsService;
import com.liquidnet.service.platform.utils.DataUtils;
import com.liquidnet.service.platform.utils.MongoVoUtils;
import com.liquidnet.service.platform.utils.OrderUtils;
import com.mongodb.BasicDBObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;


/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-20
 */
@Service
@Slf4j
public class DMCheckOrderTimeImpl extends ServiceImpl<KylinOrderTicketsMapper, KylinOrderTickets> {

    @Autowired
    private DataUtils dataUtils;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoConverter mongoConverter;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private KylinOrderTicketsMapper orderTicketsMapper;
    @Autowired
    private KylinOrderTicketStatusMapper orderTicketStatusMapper;
    @Autowired
    private KylinOrderTicketRelationsMapper orderTicketRelationsMapper;

    public boolean checkOrderTime(String userId) {
        String lock = "order_lock:checkOrderTime:" + userId;
        List<OrderScriptDto> dtoData = orderTicketsMapper.orderScriptDto(userId);
        LocalDateTime now = LocalDateTime.now();
        Long currentTime = System.currentTimeMillis();
        HashMap<String, Integer> mapSurplusGeneral = new HashMap<>();
        ArrayList<String> orderDataList = new ArrayList<>();
        ArrayList<String> orderIdList = new ArrayList<>();
        HashMap<String, Object> mapMongo = new HashMap<>();

        for (OrderScriptDto item : dtoData) {
            if (item.getStatus().equals(KylinTableStatusConst.ORDER_STATUS0)) {
                try {
                    //vo
                    mapMongo.put("status", KylinTableStatusConst.ORDER_STATUS2);
                    mapMongo.put("updatedAt", DateUtil.Formatter.yyyyMMddHHmmssSSS.format(now));
                    mapMongo.put("changeDate", now);
                    orderDataList.add(item.getOrderTicketsId() + "," + item.getUserId());
                    orderIdList.add(item.getOrderTicketsId());
                    mapSurplusGeneral.put(item.getTicketId(), mapSurplusGeneral.get(item.getTicketId()) == null ? item.getNumber() : mapSurplusGeneral.get(item.getTicketId()) + item.getNumber());
                } catch (Exception e) {
                    log.debug("CHECK TIME SYNC = " + e.getMessage());
                    e.printStackTrace();
                    return false;
                }
            } else {
            }
        }
        currentTime = System.currentTimeMillis() - currentTime;
        log.debug("FOR 循环 -> time:" + (currentTime) + "毫秒");

        if (orderDataList.size() > 0) {
            //mysql
            KylinOrderTickets orderTickets = new KylinOrderTickets();
            orderTickets.setUpdatedAt(now);
            orderTicketsMapper.update(orderTickets, new UpdateWrapper<KylinOrderTickets>().in("order_tickets_id", orderIdList));

            KylinOrderTicketStatus orderTicketStatus = new KylinOrderTicketStatus();
            orderTicketStatus.setStatus(2);
            orderTicketStatus.setUpdatedAt(now);
            orderTicketStatusMapper.update(orderTicketStatus, new UpdateWrapper<KylinOrderTicketStatus>().in("order_id", orderIdList));

            KylinOrderTicketRelations orderTicketRelations = new KylinOrderTicketRelations();
            orderTicketRelations.setUpdatedAt(now);
            orderTicketRelationsMapper.update(orderTicketRelations, new UpdateWrapper<KylinOrderTicketRelations>().in("order_id", orderIdList));

            currentTime = System.currentTimeMillis() - currentTime;
            log.debug("mysql -> time:" + (currentTime) + "毫秒");

            //库存
            for (Map.Entry<String, Integer> entry : mapSurplusGeneral.entrySet()) {
                dataUtils.changeSurplusGeneral(entry.getKey(), entry.getValue());
            }
            currentTime = System.currentTimeMillis() - currentTime;
            log.debug("redis 库存 -> time:" + (currentTime) + "毫秒");

            try {
                //mongo
                mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateMany(
                        Query.query(Criteria.where("orderTicketsId").in(orderIdList)).getQueryObject(),
                        new BasicDBObject("$set", mongoConverter.convertToMongoType(mapMongo))
                );
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("mongo -> time:" + (currentTime) + "毫秒");
            } catch (Exception e) {

            }

            int forSize = 500;
            int forCount = orderDataList.size() % forSize == 0 ? orderDataList.size() / forSize : (orderDataList.size() / forSize) + 1;
            for (int i = 0; i < forCount; i++) {
                LinkedList<String> mqList = new LinkedList<>();
                for (int y = 0; y < forSize; y++) {
                    try {
                        String t = orderDataList.get(i * 500 + y);
                        mqList.add(t);
                    } catch (Exception e) {
                        break;
                    }
                }
                log.debug("MQLIST SIZE  = " + mqList.size());
                rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CLOSE, MQConst.ROUTING_KEY_SQL_ORDER_CLOSE, OrderCloseMapping.get(mqList));
            }
        }
        return true;
    }
}
