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

import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.PagedResult;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.dto.manage.GoblinStoreMgtNoticeFilterParam;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreNoticeVo;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreMgtNoticeService;
import com.liquidnet.service.goblin.util.GoblinMongoUtils;
import com.liquidnet.service.goblin.util.GoblinRedisUtils;
import com.liquidnet.service.goblin.util.ObjectUtil;
import com.liquidnet.service.goblin.util.QueueUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 店铺公告 服务实现类
 * </p>
 *
 * @author zhanggb
 * Created by IntelliJ IDEA at 2022/1/17
 */
@Slf4j
@Service
public class GoblinStoreMgtNoticeServiceImpl implements IGoblinStoreMgtNoticeService {
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    GoblinMongoUtils goblinMongoUtils;

    @Override
    public PagedResult<GoblinStoreNoticeVo> pageList(GoblinStoreMgtNoticeFilterParam filterParam) {
        log.info("====={}", JsonUtils.toJson(goblinRedisUtils.getStoreNoticeVo(filterParam.getStoreId(), LocalDateTime.now())));
        PagedResult<GoblinStoreNoticeVo> storeNoticeVoPagedResult = goblinMongoUtils.getStoreNoticeVos(filterParam);
        if (!CollectionUtils.isEmpty(storeNoticeVoPagedResult.getList())) {
            List<GoblinStoreNoticeVo> storeNoticeVoList = ObjectUtil.getGoblinStoreNoticeVoArrayList();
            LocalDateTime now = LocalDateTime.now();
            storeNoticeVoPagedResult.getList().forEach(r -> {
                if (r.getStatus().equals("0") && r.getReleaseTime().isBefore(now)) {
                    r.setStatus("1");
                    r.setUpdatedAt(r.getReleaseTime());
                    storeNoticeVoList.add(r);
                }
            });
            if (!CollectionUtils.isEmpty(storeNoticeVoList) && goblinMongoUtils.updateStoreNoticeVoByBulk(storeNoticeVoList)) {
                List<String> noticeIdList = storeNoticeVoList.stream().map(GoblinStoreNoticeVo::getNoticeId).collect(Collectors.toList());
                List<GoblinStoreNoticeVo> storeNoticeVos = goblinRedisUtils.getStoreNoticeVos(filterParam.getStoreId(), now);
                boolean toUpdateFlg = false;
                for (GoblinStoreNoticeVo r : storeNoticeVos) {
                    if (noticeIdList.contains(r.getNoticeId())) {
                        r.setStatus("1");
                        r.setUpdatedAt(r.getReleaseTime());
                        toUpdateFlg = true;
                    }
                }
                if (toUpdateFlg) {
                    goblinRedisUtils.setStoreNoticeVos(filterParam.getStoreId(), storeNoticeVos);
                }
            }
        }
        return storeNoticeVoPagedResult;
    }

    @Override
    public void addSave(GoblinStoreNoticeVo storeNoticeVo) {
        goblinMongoUtils.setStoreNoticeVo(storeNoticeVo);

        List<GoblinStoreNoticeVo> storeNoticeVos = goblinRedisUtils.getStoreNoticeVos(storeNoticeVo.getStoreId(), storeNoticeVo.getCreatedAt());
        storeNoticeVos.add(storeNoticeVo);

        goblinRedisUtils.setStoreNoticeVos(storeNoticeVo.getStoreId(),
                storeNoticeVos.stream().sorted(Comparator.comparing(GoblinStoreNoticeVo::getReleaseTime).thenComparing(GoblinStoreNoticeVo::getCreatedAt)).collect(Collectors.toList()));

        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_STORE.getKey(),
                SqlMapping.get("goblin_store_notice.insert",
                        storeNoticeVo.getNoticeId(), storeNoticeVo.getStoreId(), storeNoticeVo.getContent(),
                        storeNoticeVo.getReleaseTime(), storeNoticeVo.getLongLasting(), storeNoticeVo.getCancellTime(),
                        storeNoticeVo.getStatus(), storeNoticeVo.getCreatedBy(), storeNoticeVo.getCreatedAt())
        );
    }

    @Override
    public boolean editSave(GoblinStoreNoticeVo updateStoreNoticeVo) {
        if (goblinMongoUtils.updateStoreNoticeVo(updateStoreNoticeVo)) {
            String storeId = updateStoreNoticeVo.getStoreId();
            List<GoblinStoreNoticeVo> storeNoticeVos = goblinRedisUtils.getStoreNoticeVos(storeId, updateStoreNoticeVo.getUpdatedAt());
            storeNoticeVos.forEach(r -> {
                if (r.getNoticeId().equals(updateStoreNoticeVo.getNoticeId())) {
                    r.setContent(updateStoreNoticeVo.getContent());
                    r.setReleaseTime(updateStoreNoticeVo.getReleaseTime());
                    r.setLongLasting(updateStoreNoticeVo.getLongLasting());
                    r.setCancellTime(updateStoreNoticeVo.getCancellTime());
                    r.setStatus(updateStoreNoticeVo.getStatus());
                    r.setUpdatedBy(updateStoreNoticeVo.getUpdatedBy());
                    r.setUpdatedAt(updateStoreNoticeVo.getUpdatedAt());
                }
            });

            goblinRedisUtils.setStoreNoticeVos(storeId,
                    storeNoticeVos.stream().sorted(Comparator.comparing(GoblinStoreNoticeVo::getReleaseTime).thenComparing(GoblinStoreNoticeVo::getCreatedAt)).collect(Collectors.toList()));

            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_STORE.getKey(),
                    SqlMapping.get("goblin_store_notice.update",
                            updateStoreNoticeVo.getContent(), updateStoreNoticeVo.getReleaseTime(), updateStoreNoticeVo.getLongLasting(),
                            updateStoreNoticeVo.getCancellTime(), updateStoreNoticeVo.getStatus(), updateStoreNoticeVo.getUpdatedBy(),
                            updateStoreNoticeVo.getUpdatedAt(), updateStoreNoticeVo.getNoticeId())
            );
        }
        return false;
    }

    @Override
    public boolean releaseProcessing(String uid, String storeId, List<String> noticeIdList) {
        LocalDateTime now = LocalDateTime.now();
        if (goblinMongoUtils.updateStoreNoticeVoByRelease(uid, now, storeId, noticeIdList)) {
            List<GoblinStoreNoticeVo> storeNoticeVos = goblinRedisUtils.getStoreNoticeVos(storeId, now);
            storeNoticeVos.forEach(r -> {
                if (noticeIdList.contains(r.getNoticeId())) {
                    r.setReleaseTime(now);
                    r.setStatus("1");
                    r.setUpdatedBy(uid);
                    r.setUpdatedAt(now);
                }
            });
            goblinRedisUtils.setStoreNoticeVos(storeId, storeNoticeVos);

            LinkedList<Object[]> updateStoreNoticeObjs = CollectionUtil.linkedListObjectArr();
            noticeIdList.forEach(noticeId -> updateStoreNoticeObjs.add(new Object[]{now, uid, now, storeId, noticeId}));
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_STORE.getKey(),
                    SqlMapping.get("goblin_store_notice.release", updateStoreNoticeObjs));

            return true;
        }
        return false;
    }

    @Override
    public boolean removeProcessing(String uid, String storeId, List<String> noticeIdList) {
        LocalDateTime now = LocalDateTime.now();
        if (goblinMongoUtils.updateStoreNoticeVoByRemove(uid, now, storeId, noticeIdList)) {
            List<GoblinStoreNoticeVo> storeNoticeVos = goblinRedisUtils.getStoreNoticeVos(storeId, now);
            storeNoticeVos.removeIf(r -> noticeIdList.contains(r.getNoticeId()));
            goblinRedisUtils.setStoreNoticeVos(storeId, storeNoticeVos);

            LinkedList<Object[]> revStoreNoticeObjs = CollectionUtil.linkedListObjectArr();
            noticeIdList.forEach(noticeId -> revStoreNoticeObjs.add(new Object[]{uid, now, storeId, noticeId}));
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.SQL_STORE.getKey(),
                    SqlMapping.get("goblin_store_notice.remove", revStoreNoticeObjs));

            return true;
        }
        return false;
    }

}
