package com.tanpu.community.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tanpu.common.api.CommonResp;
import com.tanpu.common.exception.BizException;
import com.tanpu.common.util.JsonUtil;
import com.tanpu.common.uuid.UuidGenHelper;
import com.tanpu.community.api.beans.vo.feign.fatools.UserInfoResp;
import com.tanpu.community.api.constants.RedisKeyConstant;
import com.tanpu.community.api.enums.DeleteTagEnum;
import com.tanpu.community.api.enums.NotificationTypeEnum;
import com.tanpu.community.cache.RedisCache;
import com.tanpu.community.dao.entity.NotificationForwardDO;
import com.tanpu.community.dao.entity.NotificationLikeDO;
import com.tanpu.community.dao.entity.community.NotificationEntity;
import com.tanpu.community.dao.mapper.community.NotificationMapper;
import com.tanpu.community.feign.fatools.FeignClientForFatools;
import com.tanpu.community.util.TimeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class NotificationService {

    @Resource
    private NotificationMapper notificationMapper;

    @Autowired
    private UuidGenHelper uuidGenHelper;

    @Autowired
    private FeignClientForFatools feignClientForFatools;


    @Autowired
    private RedisCache redisCache;


    public void insert(String operatorId,String notifierId,NotificationTypeEnum type,String targetId,String content){
        NotificationEntity entity = NotificationEntity.builder().operatorId(operatorId)
                .notificationId(uuidGenHelper.getUuidStr())
                .notifiedUserId(notifierId)
                .messageType(type.getCode())
                .content(content)
                .operatorId(operatorId)
                .targetId(targetId)
                .build();
        insert(entity);
    }

    public void insert(String operatorId, String notifierId, NotificationTypeEnum type, String targetId, String content
            , LocalDateTime createTime){
        NotificationEntity entity = NotificationEntity.builder().operatorId(operatorId)
                .notificationId(uuidGenHelper.getUuidStr())
                .notifiedUserId(notifierId)
                .messageType(type.getCode())
                .content(content)
                .operatorId(operatorId)
                .targetId(targetId)
                .createTime(createTime)
                .updateTime(createTime)
                .build();
        insert(entity);
    }


    public void insertForward(String operatorId,String notifierId,String themeId,String topicId,String text){
        NotificationForwardDO forwardDO = NotificationForwardDO.builder().topicId(topicId).content(text).build();
        NotificationEntity entity = NotificationEntity.builder().operatorId(operatorId)
                .notificationId(uuidGenHelper.getUuidStr())
                .notifiedUserId(notifierId)
                .messageType(NotificationTypeEnum.FORWARD.getCode())
                .content(JsonUtil.toJson(forwardDO))
                .operatorId(operatorId)
                .targetId(themeId)
                .build();
        insert(entity);

    }


    public void insertLike(String operatorId,String notifierId,String targetId){
        NotificationEntity entity = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getMessageType, NotificationTypeEnum.LIKE.getCode())
                .eq(NotificationEntity::getTargetId,targetId)
                .eq(NotificationEntity::getNotifiedUserId, notifierId));
        if (entity!=null){
            NotificationLikeDO notificationLikeDO = JsonUtil.toBean(entity.getContent(), NotificationLikeDO.class);
            notificationLikeDO.addItem(operatorId);
            entity.setContent(JsonUtil.toJson(notificationLikeDO));
            entity.setUpdateTime(LocalDateTime.now());
            notificationMapper.updateById(entity);
        }else {
            NotificationLikeDO notificationLikeDO = new NotificationLikeDO();
            notificationLikeDO.addItem(operatorId);
            NotificationEntity build = NotificationEntity.builder().operatorId(operatorId)
                    .notificationId(uuidGenHelper.getUuidStr())
                    .messageType(NotificationTypeEnum.LIKE.getCode())
                    .notifiedUserId(notifierId)
                    .content(JsonUtil.toJson(notificationLikeDO))
                    .targetId(targetId)
                    .operatorId(operatorId)
                    .build();
            insert(build);
        }

    }

    @Transactional
    public void insert(NotificationEntity entity){
        notificationMapper.insert(entity);
    }


    public NotificationEntity queryById(String notificationId){
        return notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getNotificationId,notificationId));
    }


    public List<NotificationEntity> query(String userId, Integer type, String lastId, Integer pageSize){
        LambdaQueryWrapper<NotificationEntity> queryWrapper = new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getNotifiedUserId, userId)
                .orderByDesc(NotificationEntity::getUpdateTime)
                .last("limit " + pageSize);


        if (StringUtils.isNotBlank(lastId)){
            NotificationEntity lastOne = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                    .eq(NotificationEntity::getNotificationId, lastId));
            queryWrapper.lt(NotificationEntity::getUpdateTime, lastOne.getCreateTime());
        }
        if (!NotificationTypeEnum.ALL.getCode().equals(type)){
            queryWrapper.eq(NotificationEntity::getMessageType,type);
        }
        return notificationMapper.selectList(queryWrapper);
    }


    public void truncate() {
        notificationMapper.delete(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode()));
    }

    public void insertLike(String operatorId, String notifierId, String targetId, LocalDateTime updateTime){
        NotificationEntity entity = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getMessageType, NotificationTypeEnum.LIKE.getCode())
                .eq(NotificationEntity::getTargetId,targetId)
                .eq(NotificationEntity::getNotifiedUserId, notifierId));
        if (entity!=null){
            NotificationLikeDO notificationLikeDO = JsonUtil.toBean(entity.getContent(), NotificationLikeDO.class);
            notificationLikeDO.addItem(operatorId);

            entity.setContent(JsonUtil.toJson(notificationLikeDO));
            entity.setUpdateTime(updateTime);
            notificationMapper.updateById(entity);
        }else {
            NotificationLikeDO notificationLikeDO = new NotificationLikeDO();
            notificationLikeDO.addItem(operatorId);
            NotificationEntity build = NotificationEntity.builder().operatorId(operatorId)
                    .notificationId(uuidGenHelper.getUuidStr())
                    .messageType(NotificationTypeEnum.LIKE.getCode())
                    .notifiedUserId(notifierId)
                    .content(JsonUtil.toJson(notificationLikeDO))
                    .targetId(targetId)
                    .operatorId(operatorId)
                    .createTime(updateTime)
                    .updateTime(updateTime)
                    .build();
            insert(build);
        }

    }

    // 消息通知队列缓存
    public void putNotifyCache(String notifyUserId, String operatorId, NotificationTypeEnum type){
        UserInfoResp userInfo = getUserInfo(operatorId);
        redisCache.incr(RedisKeyConstant.MESSAGE_NOTIFY_COUNT + notifyUserId);
        redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName()+type.getType()+"了你的内容", 60 * 60 * 24 * 30);
        redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId, TimeUtils.format(LocalDateTime.now()), 60 * 60 * 24 * 30);
    }


    // 消息通知队列缓存
    public void putNotifyCacheFollow(String notifyUserId, String operatorId) {
        UserInfoResp userInfo = getUserInfo(operatorId);
        redisCache.incr(RedisKeyConstant.MESSAGE_NOTIFY_COUNT + notifyUserId);
        redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "关注了你", 60 * 60 * 24 * 30);
        redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId, TimeUtils.format(LocalDateTime.now()), 60 * 60 * 24 * 30);
    }

    private UserInfoResp getUserInfo(String authorId) {
        CommonResp<UserInfoResp> userInfoNewCommonResp = feignClientForFatools.queryUserInfoNew(authorId);
        if (userInfoNewCommonResp.isNotSuccess()) {
            throw new BizException("内部接口调用失败");
        }
        return userInfoNewCommonResp.getData();
    }

}