package com.sonic.frog.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.sonic.frog.dao.AiUserStatDao;
import com.sonic.frog.domain.entity.AiUser;
import com.sonic.frog.domain.entity.AiUserStat;
import com.sonic.frog.domain.output.AiUserStatOutput;
import com.sonic.frog.enums.Constants;
import com.sonic.frog.event.inner.payload.AiUserStatPayload;
import com.sonic.frog.service.AiUserSearchService;
import com.sonic.frog.service.AiUserStatService;
import com.sonic.frog.utils.BeanConver;
import com.sonic.frog.utils.LimitUtils;
import com.sonic.frog.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * AI用户统计业务实现类
 */
@Service
@Slf4j
public class AiUserStatServiceImpl extends ServiceImpl<AiUserStatDao, AiUserStat> implements AiUserStatService {

    @Autowired
    private AiUserStatDao aiUserStatDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisKeyUtils redisKeyUtils;
    @Autowired
    private AiUserSearchService aiUserSearchService;

    @Override
    public AiUserStatOutput getAiUserStatByAiId(Long aiId, Long currentUserId) {
        AiUserStat aiUserStat = getOne(Wrappers.<AiUserStat>lambdaQuery().eq(AiUserStat::getAiId, aiId).last("limit 1"));
        AiUserStatOutput output = BeanConver.copeBean(aiUserStat, AiUserStatOutput.class);
        //查看是否是当前用户的ai,如果不是则coinNum返回null
        AiUser aiUser = aiUserSearchService.getAiUserByAiId(aiId);
        if (currentUserId != null && aiUser != null && !aiUser.getUserId().equals(currentUserId)) {
            output.setCoinNum(0L);
        }
        return output;
    }

    @Override
    public void initAiUserStat(Long aiId) {
        AiUserStat aiUserStat = new AiUserStat();
        aiUserStat.setAiId(aiId);
        aiUserStat.setLikedNum(0);
        aiUserStat.setChatNum(0);
        aiUserStat.setConversationNum(0);
        aiUserStat.setCoinNum(0L);
        aiUserStat.setGiftCoinNum(0L);
        aiUserStat.setUnlockImgCoinNum(0L);
        aiUserStat.setHeartbeatValTotal(new BigDecimal(0));
        aiUserStat.setCreateTime(LocalDateTime.now());
        aiUserStat.setEditTime(LocalDateTime.now());
        save(aiUserStat);
    }

    @Override
    public void aiUserStat(AiUserStatPayload payload) {
        AiUserStatPayload.Type type = payload.getType();
        switch (type) {
            case LIKED:
                aiUserStatDao.updateLikedNum(payload.getAiId(), 1);
                break;
            case CANCEL_LIKED:
                aiUserStatDao.updateLikedNum(payload.getAiId(), -1);
                aiUserStatDao.updateDislikedNum(payload.getAiId(), 1);
                break;
            case CHAT:
                increaseChatNum(payload.getAiId());
                break;
            case FIRST_CHAT:
                increaseConversationNum(payload.getAiId());
                break;
            case GIFT:
                //统计礼物打赏coin
                increaseGiftCoinNum(payload.getAiId(), payload.getCoinNum());
                //统计总coin
                increaseCoinNum(payload.getAiId(), payload.getCoinNum());
                break;
            case UNLOCK_IMG:
                //统计解锁图片coin
                increaseUnlockImgCoinNum(payload.getAiId(), payload.getCoinNum());
                //统计总coin
                increaseCoinNum(payload.getAiId(), payload.getCoinNum());
                break;
            default:
        }
    }

    @Override
    public void updateLikeNum(Long aiId, Integer num) {
        aiUserStatDao.updateLikedNum(aiId, num);
    }

    @Override
    public void increaseChatNum(Long aiId) {
        //聊天次数 redis累加，累加到20次时，更新一次 未达到聊天20次，定时任务每隔5分钟更新一次
        String aiChatNumKey = redisKeyUtils.aiChatNumKey();
        Double chatNum = stringRedisTemplate.opsForZSet().score(aiChatNumKey, aiId.toString());
        if (chatNum != null) {
            stringRedisTemplate.opsForZSet().add(aiChatNumKey, aiId.toString(), chatNum + 1);
            //达到20次更新到数据库
            if (chatNum + 1 == 20) {
                //更新到数据库
                aiUserStatDao.increaseChatNum(aiId, 20);
                //
                stringRedisTemplate.opsForZSet().remove(aiChatNumKey, aiId.toString());
            }
        } else {
            stringRedisTemplate.opsForZSet().add(aiChatNumKey, aiId.toString(), 1);
        }
    }

    @Override
    public void increaseChatNum(Long aiId, Integer num) {
        //更新到数据库
        aiUserStatDao.increaseChatNum(aiId, num);
    }

    @Override
    public void increaseConversationNum(Long aiId) {
        aiUserStatDao.increaseConversationNum(aiId);
    }

    public void increaseGiftCoinNum(Long aiId, Long coinNum) {
        aiUserStatDao.increaseGiftCoinNum(aiId, coinNum);
    }

    public void increaseUnlockImgCoinNum(Long aiId, Long coinNum) {
        aiUserStatDao.increaseUnlockImgCoinNum(aiId, coinNum);
    }

    @Override
    public void increaseCoinNum(Long aiId, Long coinNum) {
        //统计用户实际coin
        coinNum = new BigDecimal(coinNum).multiply(Constants.USER_RATE).longValue();
        aiUserStatDao.increaseCoinNum(aiId, coinNum);
    }

    @Override
    public Map<Long, Integer> queryAiLikedCount(List<Long> aiIds) {
        if (CollectionUtils.isEmpty(aiIds)) {
            return Collections.emptyMap();
        }
        List<AiUserStat> list = list(Wrappers.<AiUserStat>lambdaQuery()
                .select(AiUserStat::getAiId, AiUserStat::getLikedNum)
                .in(AiUserStat::getAiId, aiIds)
        );
        if (CollectionUtils.isNotEmpty(list)) {
            return list.stream().collect(Collectors.toMap(AiUserStat::getAiId, AiUserStat::getLikedNum));
        }
        return Collections.emptyMap();
    }

    @Override
    public Integer getAiLikedCount(Long aiId) {
        Map<Long, Integer> likedCountMap = queryAiLikedCount(Lists.newArrayList(aiId));
        return likedCountMap.get(aiId) != null ? likedCountMap.get(aiId) : 0;
    }
}