package com.liquidnet.service.adam.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.common.mq.constant.MQConst;
import com.liquidnet.commons.lang.util.BsonUtil;
import com.liquidnet.service.adam.dto.vo.AdamEntersVo;
import com.liquidnet.service.adam.entity.AdamEnters;
import com.liquidnet.service.adam.mapper.AdamEntersMapper;
import com.liquidnet.service.adam.service.IAdamEntersService;
import com.liquidnet.service.adam.service.IAdamRdmService;
import com.liquidnet.service.base.SqlMapping;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
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 org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * 入场人 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-04-28
 */
@Slf4j
@Service
public class AdamEntersServiceImpl extends ServiceImpl<AdamEntersMapper, AdamEnters> implements IAdamEntersService {
    @Autowired
    AdamEntersMapper adamEntersMapper;
    @Autowired
    MongoConverter mongoConverter;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @Autowired
    IAdamRdmService adamRdmService;

//    @Override
//    public List<AdamEnters> queryByUid(String uid) {
//        List<AdamEnters> infoList = new ArrayList<>();
//
//        Map<Object, Object> objectMap = redisUtil.hmget(AdamRedisConst.INFO_ENTERS.concat(uid));
//
//        if (CollectionUtils.isEmpty(objectMap)) {
//            infoList = mongoTemplate.find(Query.query(Criteria.where("uid").is(uid).and("state").is(1)), AdamEnters.class, AdamEnters.class.getSimpleName());
//        } else {
//            Collection<Object> values = objectMap.values();
//            for (Object o : values) {
//                infoList.add((AdamEnters) o);
//            }
//        }
//
//        return infoList;
//    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void add(AdamEnters info) {
        List<AdamEnters> entersList = adamRdmService.getEntersByUid(info.getUid());

        info.setIsDefault(CollectionUtils.isEmpty(entersList));

        mongoTemplate.insert(info, AdamEnters.class.getSimpleName());

        List<Object> paramList = new ArrayList<>();
        paramList.add(info.getEntersId());
        paramList.add(info.getUid());
        paramList.add(info.getType());
        paramList.add(info.getName());
        paramList.add(info.getMobile());
        paramList.add(info.getIdCard());
        paramList.add(info.getIsDefault());
        paramList.add(info.getState());
        paramList.add(info.getCreatedAt());
        paramList.add(info.getUpdatedAt());
        paramList.add(info.getDeletedAt());
        paramList.add(info.getComment());

        String mqMsg = SqlMapping.get("adam_enters.add", paramList.toArray());
        log.info("mq.sql:{}", mqMsg);

        rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL, MQConst.ROUTING_KEY_SQL,
                mqMsg);

        entersList.add(info);
        adamRdmService.setEntersByUid(info.getUid(), entersList);
    }

//    @Override
//    public AdamEnters query(String uid, String entersId) {
//        AdamEnters info = (AdamEnters) redisUtil.hget(AdamRedisConst.INFO_ENTERS.concat(uid), entersId);
//
//        if (null == info) {
//            info = mongoTemplate.findOne(
//                    Query.query(Criteria.where("entersId").is(entersId).and("state").is(1).and("uid").is(uid)),
//                    AdamEnters.class, AdamEnters.class.getSimpleName());
//
//            if (null != info) redisUtil.hset(AdamRedisConst.INFO_ENTERS.concat(uid), entersId, info);
//        }
//        return info;
//    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void def(String uid, String entersId) {
        LocalDateTime now = LocalDateTime.now();
        LinkedList<Object[]> linkedList = new LinkedList<>();
        List<AdamEnters> entersList = adamRdmService.getEntersByUid(uid);
        if (entersList.size() > 1) {// 取消原默认
            AdamEnters unDeaultEnters = new AdamEnters();
            unDeaultEnters.setIsDefault(false);
            unDeaultEnters.setUpdatedAt(now);
            BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(unDeaultEnters));
            Document doc = mongoTemplate.getCollection(AdamEnters.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("uid").is(uid).and("state").is(1).and("isDefault").is(true)).getQueryObject(),
                    object, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );
            if (null != doc) {
                AdamEnters enters = BsonUtil.toBean(doc, AdamEnters.class);

                List<Object> paramList = new ArrayList<>();
                paramList.add(unDeaultEnters.getIsDefault());
                paramList.add(unDeaultEnters.getUpdatedAt());
                paramList.add(enters.getEntersId());
//            rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL, MQConst.ROUTING_KEY_SQL,
//                    SqlMapping.get("adam_enters.update.is_default", paramList.toArray()));
                linkedList.add(paramList.toArray());

                entersList.removeIf(r -> r.getEntersId().equals(enters.getEntersId()));

                entersList.add(enters);
            }
        }
        {// 设置新默认
            AdamEnters defaultEnters = new AdamEnters();
            defaultEnters.setIsDefault(true);
            defaultEnters.setUpdatedAt(now);
            BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(defaultEnters));
            Document doc = mongoTemplate.getCollection(AdamEnters.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("uid").is(uid).and("entersId").is(entersId)).getQueryObject(),
                    object, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );
            AdamEnters enters = BsonUtil.toBean(doc, AdamEnters.class);

            List<Object> paramList = new ArrayList<>();
            paramList.add(defaultEnters.getIsDefault());
            paramList.add(defaultEnters.getUpdatedAt());
            paramList.add(entersId);
//            rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL, MQConst.ROUTING_KEY_SQL,
//                    SqlMapping.get("adam_enters.update.is_default", paramList.toArray()));
            linkedList.add(paramList.toArray());

            entersList.removeIf(r -> r.getEntersId().equals(enters.getEntersId()));

            entersList.add(enters);
        }
        adamRdmService.setEntersByUid(uid, entersList);

//        rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL, MQConst.ROUTING_KEY_SQL,
//                SqlMapping.get("adam_enters.update.is_default", linkedList));
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void edit(AdamEnters info) {
        BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(info));
        Document doc = mongoTemplate.getCollection(AdamEnters.class.getSimpleName()).findOneAndUpdate(
                Query.query(Criteria.where("entersId").is(info.getEntersId())).getQueryObject(),
                object, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
        );

        List<Object> paramList = new ArrayList<>();
        paramList.add(info.getType());
        paramList.add(info.getName());
        paramList.add(info.getMobile());
        paramList.add(info.getIdCard());
        paramList.add(info.getIsDefault());
        paramList.add(info.getState());
        paramList.add(info.getUpdatedAt());
        paramList.add(info.getEntersId());
//        rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL, MQConst.ROUTING_KEY_SQL,
//                SqlMapping.get("adam_enters.edit", paramList.toArray()));

        List<AdamEnters> entersList = adamRdmService.getEntersByUid(info.getUid());
        entersList.removeIf(r -> r.getEntersId().equals(info.getEntersId()));
        entersList.add(info);
        adamRdmService.setEntersByUid(info.getUid(), entersList);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void remove(String uid, String entersId) {
        AdamEnters enters = new AdamEnters();
        enters.setUpdatedAt(LocalDateTime.now());
        enters.setDeletedAt(enters.getUpdatedAt());
        enters.setState(2);

        BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(enters));
        UpdateResult updateResult = mongoTemplate.getCollection(AdamEnters.class.getSimpleName())
                .updateOne(Query.query(Criteria.where("entersId").is(entersId)).getQueryObject(), object);

        List<Object> paramList = new ArrayList<>();
        paramList.add(enters.getUpdatedAt());
        paramList.add(enters.getDeletedAt());
        paramList.add(entersId);
//        rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL, MQConst.ROUTING_KEY_SQL,
//                SqlMapping.get("adam_enters.remove", paramList.toArray()));

        List<AdamEnters> entersList = adamRdmService.getEntersByUid(uid);
        entersList.removeIf(r -> r.getEntersId().equals(entersId));
        adamRdmService.setEntersByUid(uid, entersList);
    }

    @Override
    public AdamEntersVo queryDefault(String uid) {
        List<AdamEnters> list = adamRdmService.getEntersByUid(uid);

        if (!CollectionUtils.isEmpty(list)) {
            AdamEnters defaultVo = null;
            for (AdamEnters l : list) {
                if (l.getIsDefault()) {
                    return AdamEntersVo.getNew().copy(l);
                }
                defaultVo = null == defaultVo ? l :
                        l.getCreatedAt().isAfter(defaultVo.getCreatedAt()) ? l : defaultVo;
            }
            return AdamEntersVo.getNew().copy(defaultVo);
        }
        return null;
    }
}
