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

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.GoblinOrderSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreMarketVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderVo;
import com.liquidnet.service.goblin.entity.GoblinStoreOrder;
import com.liquidnet.service.goblin.mapper.GoblinStoreOrderMapper;
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.platform.utils.GoblinRedisUtils;
import com.liquidnet.service.platform.utils.ObjectUtil;
import com.liquidnet.service.platform.utils.QueueUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
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.*;

import static com.liquidnet.commons.lang.util.DateUtil.DTF_YMD_HMS;


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

    @Autowired
    private GoblinRedisUtils goblinRedisUtils;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoConverter mongoConverter;
    @Autowired
    private QueueUtils queueUtils;

    public boolean checkOrderTime() {
        LocalDateTime now = LocalDateTime.now();
        for (int i = 0; i < goblinRedisUtils.randomMax; i++) {
            List<String> orderIds = goblinRedisUtils.getUnPayGoblinOrderList(i + "");
            for (String orderId : orderIds) {
                GoblinStoreOrderVo orderVo = goblinRedisUtils.getGoblinOrder(orderId);
                if (orderVo == null || orderVo.getCreatedAt() == null) {
                    goblinRedisUtils.removeGoblinOrder(i + "", orderId);
                    continue;
                }
                log.debug("ORDERDATA = " + orderVo);
                LocalDateTime expireTime = LocalDateTime.parse(orderVo.getCreatedAt(), DTF_YMD_HMS).plusMinutes(orderVo.getPayCountdownMinute() + 1);
                if (now.isAfter(expireTime) && orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_0.getValue()) {//过期
                    LinkedList<String> sqls = CollectionUtil.linkedListString();
                    LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
                    LinkedList<Object[]> sqlDataSku = CollectionUtil.linkedListObjectArr();
                    sqls.add(SqlMapping.get("goblin_order.close.order"));
                    sqls.add(SqlMapping.get("goblin_order.close.sku"));
                    for (String orderSkuId : orderVo.getOrderSkuVoIds()) {
                        GoblinOrderSkuVo skuVo = goblinRedisUtils.getGoblinOrderSkuVo(orderSkuId);
                        //订单详情
                        skuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_5.getValue());
                        updateGoblinOrderSkuVo(skuVo.getOrderSkuId(), skuVo);
                        goblinRedisUtils.setGoblinOrderSku(skuVo.getOrderSkuId(), skuVo);
                        //库存&限购&&待支付订单
                        String pre = GoblinStatusConst.MarketPreStatus.getPre(skuVo.getSkuId());
                        goblinRedisUtils.incrSkuStock(pre, skuVo.getSkuId(), skuVo.getNum());
                        goblinRedisUtils.decrSkuCountByUid(orderVo.getUserId(), skuVo.getSkuId(), skuVo.getNum());
                        //mysql
                        sqlDataSku.add(new Object[]{
                                skuVo.getStatus(), now, orderVo.getOrderId(), now, now
                        });
                    }
                    //订单
                    orderVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_5.getValue());
                    updateGoblinStoreOrderVo(orderVo.getOrderId(), orderVo);
                    goblinRedisUtils.setGoblinOrder(orderVo.getOrderId(), orderVo);
                    goblinRedisUtils.removeGoblinOrder(i + "", orderVo.getOrderId());
                    //mysql
                    sqlDataOrder.add(new Object[]{
                            orderVo.getStatus(), now, now, "超时关闭", orderVo.getOrderId(), now, now
                    });
                    //执行sql
                    queueUtils.sendMsgByGoblinRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CLOSE.getKey(),
                            SqlMapping.gets(sqls, sqlDataOrder, sqlDataSku));
                } else if (orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_5.getValue() || orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
                    goblinRedisUtils.removeGoblinOrder(i + "", orderVo.getOrderId());
                }
            }
        }
        return true;
    }

    private UpdateResult updateGoblinStoreOrderVo(String orderId, GoblinStoreOrderVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinStoreOrderVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderId").is(orderId)).getQueryObject(),
                object);
    }

    private UpdateResult updateGoblinOrderSkuVo(String orderSkuId, GoblinOrderSkuVo data) {
        BasicDBObject object = ObjectUtil.cloneBasicDBObject().append("$set", mongoConverter.convertToMongoType(data));
        return mongoTemplate.getCollection(GoblinOrderSkuVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderSkuId").is(orderSkuId)).getQueryObject(),
                object);
    }
}
