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

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.OrderCloseMapping;
import com.liquidnet.service.base.constant.MQConst;
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.*;
import com.liquidnet.service.kylin.mapper.KylinOrderTaskMapper;
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.platform.utils.DataUtils;
import com.liquidnet.service.platform.utils.QueueUtils;
import com.mongodb.BasicDBObject;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
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 QueueUtils queueUtils;
    @Autowired
    private KylinOrderTicketsMapper orderTicketsMapper;
    @Autowired
    private KylinOrderTicketStatusMapper orderTicketStatusMapper;
    @Autowired
    private KylinOrderTicketRelationsMapper orderTicketRelationsMapper;
    @Autowired
    private KylinOrderTaskMapper orderTaskMapper;

    public boolean checkOrderTime(String 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());
                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_CLOSE.getKey(), OrderCloseMapping.get(mqList));
            }
        }
        return true;
    }

    public boolean checkTransferOrder(Integer minute) {
        LocalDateTime now = LocalDateTime.now();
        List<KylinOrderTask> task = orderTaskMapper.selectList(
                Wrappers.lambdaQuery(KylinOrderTask.class).eq(KylinOrderTask::getStatus, 10).last("and NOW() > DATE_SUB(created_at,INTERVAL -("+minute+") MINUTE)")
        );
        ArrayList<String> orderIdList = CollectionUtil.arrayListString();
        for (KylinOrderTask item : task) {
            orderIdList.add(item.getOrderId());
        }

        if (orderIdList.size() == 0) {
            return true;
        }

        //处理原订单mongo
        HashMap<String, Object> mapMongo = new HashMap<>();
        mapMongo.put("transferStatus", 0);
        mapMongo.put("transferUid", "");
        mapMongo.put("updatedAt", DateUtil.Formatter.yyyyMMddHHmmssSSS.format(now));
        mapMongo.put("changeDate", now);
        mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateMany(
                Query.query(Criteria.where("orderTicketsId").in(orderIdList)).getQueryObject(),
                new BasicDBObject("$set", mongoConverter.convertToMongoType(mapMongo))
        );
        //处理原订单mysql
        KylinOrderTicketStatus orderTicketStatus = new KylinOrderTicketStatus();
        orderTicketStatus.setTransferStatus(0);
        orderTicketStatus.setUpdatedAt(now);
        orderTicketStatusMapper.update(orderTicketStatus, new UpdateWrapper<KylinOrderTicketStatus>().in("order_id", orderIdList));
        KylinOrderTicketRelations orderTicketRelations = new KylinOrderTicketRelations();
        orderTicketRelations.setTransferUid("");
        orderTicketRelations.setUpdatedAt(now);
        orderTicketRelationsMapper.update(orderTicketRelations, new UpdateWrapper<KylinOrderTicketRelations>().in("order_id", orderIdList));
        //mysql 删除持久化数据
        orderTaskMapper.delete(Wrappers.lambdaQuery(KylinOrderTask.class).eq(KylinOrderTask::getStatus, 10).ge(KylinOrderTask::getCreatedAt, now.plusHours(2)));
        //处理原订单redis
        int forSize = 500;
        int forCount = orderIdList.size() % forSize == 0 ? orderIdList.size() / forSize : (orderIdList.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 = orderIdList.get(i * 500 + y);
                    mqList.add(t);
                } catch (Exception e) {
                    break;
                }
            }
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_TRANSFER_OVERTIME.getKey(), OrderCloseMapping.get(mqList));
        }
        return true;
    }
}
