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.google.common.collect.Sets;
import com.sonic.frog.dao.AiUserDao;
import com.sonic.frog.domain.entity.*;
import com.sonic.frog.domain.input.SetChatBubbleInput;
import com.sonic.frog.domain.output.*;
import com.sonic.frog.enums.BubbleUnlockTypeEnum;
import com.sonic.frog.enums.HeartbeatLevelEnum;
import com.sonic.frog.enums.ToastResultCode;
import com.sonic.frog.service.*;
import com.sonic.frog.utils.BeanConver;
import com.sonic.frog.utils.BeanConvert;
import com.sonic.lion.lib.client.SubscribeClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.sonic.frog.enums.Constants.DEFAULT_BACKGROUND;

/**
 * AI用户表服务实现类
 */
@Service
@Slf4j
public class AiUserSearchServiceImpl extends ServiceImpl<AiUserDao, AiUser> implements AiUserSearchService {

    @Autowired
    private AiDictService aiDictService;
    @Autowired
    private AiUserStatService aiUserStatService;
    @Autowired
    private AiUserExtService aiUserExtService;
    @Autowired
    private ChatSetService chatSetService;
    @Autowired
    private AiUserHeartbeatRelationService aiUserHeartbeatRelationService;
    @Autowired
    private ChatBubbleDictService chatBubbleDictService;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private TimbreDictService timbreDictService;
    @Autowired
    private SubscribeClient subscribeClient;
    @Autowired
    private LikedService likedService;
    @Autowired
    private ChatService chatService;
    @Autowired
    private HeartbeatLevelDictService heartbeatLevelDictService;

    @Override
    public AiUserBaseOutput getAiUserBaseInfo(Long currentUserId, Long aiId) {
        //查询基础信息
        AiUser aiUser = getOne(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getAiId, aiId));
        ToastResultCode.AI_USER_NOT_EXIST.check(aiUser == null);
        //已经删除的，用户自己是不能看到的
        ToastResultCode.AI_USER_NOT_EXIST.check(aiUser.getIsDelete() && aiUser.getUserId().equals(currentUserId));
        //已经删除的、私密的，只有有关系的人才能看到
        if (aiUser.getIsDelete() || (aiUser.getPermission() == 2 && !aiUser.getUserId().equals(currentUserId))) {
            //判断是否存在关系
            boolean isRelation = aiUserHeartbeatRelationService.relationCheck(currentUserId, aiId);
            ToastResultCode.AI_USER_NOT_EXIST.check(!isRelation);
        }

        AiUserBaseOutput output = BeanConver.copeBean(aiUser, AiUserBaseOutput.class);

        //性格，标签名称,角色名称
        Map<String, String> aiDictNameMap = aiDictService.mapNameByCodeList(Sets.newHashSet(aiUser.getRoleCode(), aiUser.getCharacterCode(), aiUser.getTagCode()));
        output.setCharacterName(aiDictNameMap.get(aiUser.getCharacterCode()));
        output.setTagName(aiDictNameMap.get(aiUser.getTagCode()));
        output.setRoleName(aiDictNameMap.get(aiUser.getRoleCode()));
        //设置点赞数
        output.setLikedCount(aiUserStatService.getAiLikedCount(aiId));
        //获取当前用户是否点赞过
        if (currentUserId != null) {
            output.setLiked(likedService.isLiked(currentUserId, aiId, Liked.BizType.AI));
        }
        return output;
    }

    @Override
    public List<AiUserBaseListOutput> getBaseUserAiList(Long userId) {
        List<AiUser> list = list(Wrappers.<AiUser>lambdaQuery()
                .eq(AiUser::getUserId, userId)
                .eq(AiUser::getIsDelete, false)
                .orderByDesc(AiUser::getId)
        );
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        //获取字典数据
        Map<String, String> aiDictNameMap = mapNameByCodeList(list);
        List<Long> aiIdList = list.stream().map(AiUser::getAiId).collect(Collectors.toList());
        //批量获取点赞数
        Map<Long, Integer> likedCountMap = aiUserStatService.queryAiLikedCount(aiIdList);

        List<AiUserBaseListOutput> outputList = Lists.newArrayList();
        for (AiUser aiUser : list) {
            AiUserBaseListOutput output = BeanConvert.copeBean(aiUser, AiUserBaseListOutput.class);
            //组装字典数据
            output.setRoleName(aiDictNameMap.get(aiUser.getRoleCode()));
            output.setCharacterName(aiDictNameMap.get(aiUser.getCharacterCode()));
            output.setTagName(aiDictNameMap.get(aiUser.getTagCode()));
            output.setLikedNum(likedCountMap.get(aiUser.getAiId()));
            outputList.add(output);
        }
        return outputList;
    }

    @Override
    public List<AiUserTargetListOutput> getTargetUserAiList(Long userId) {
        List<AiUser> list = list(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getUserId, userId)
                .eq(AiUser::getPermission, 1)
                .eq(AiUser::getIsDelete, false));
        //获取字典数据
        Map<String, String> aiDictNameMap = mapNameByCodeList(list);
        List<AiUserTargetListOutput> outputList = Lists.newArrayList();
        for (AiUser aiUser : list) {
            AiUserTargetListOutput output = BeanConvert.copeBean(aiUser, AiUserTargetListOutput.class);
            //组装字典数据
            output.setRoleName(aiDictNameMap.get(aiUser.getRoleCode()));
            output.setCharacterName(aiDictNameMap.get(aiUser.getCharacterCode()));
            output.setTagName(aiDictNameMap.get(aiUser.getTagCode()));
            outputList.add(output);
        }
        return outputList;
    }

    /**
     * 获取Ai字典数据
     *
     * @param list
     * @return
     */
    @Override
    public Map<String, String> mapNameByCodeList(List<AiUser> list) {
        //获取字典数据
        Set<String> roleCodeList = list.stream().map(AiUser::getRoleCode).collect(Collectors.toSet());
        Set<String> characterCodeList = list.stream().map(AiUser::getCharacterCode).collect(Collectors.toSet());
        Set<String> tagCodeList = list.stream().map(AiUser::getTagCode).collect(Collectors.toSet());
        //批量查询字典数据数据
        Set<String> codeList = Sets.newHashSet();
        codeList.addAll(roleCodeList);
        codeList.addAll(characterCodeList);
        codeList.addAll(tagCodeList);
        return aiDictService.mapNameByCodeList(codeList);
    }

    @Override
    public AiUserH5Output getAiUserH5Info(Long aiId) {
        AiUser aiUser = getOne(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getAiId, aiId));
        AiUserH5Output output = BeanConver.copeBean(aiUser, AiUserH5Output.class);
        //角色，性格，标签
        Map<String, String> aiDictNameMap = aiDictService.mapNameByCodeList(Sets.newHashSet(aiUser.getRoleCode(), aiUser.getCharacterCode(), aiUser.getTagCode()));
        output.setCharacterName(aiDictNameMap.get(aiUser.getCharacterCode()));
        output.setTagName(aiDictNameMap.get(aiUser.getTagCode()));
        output.setRoleName(aiDictNameMap.get(aiUser.getRoleCode()));
        //对话开场白
        AiUserExt aiUserExt = aiUserExtService.getAiUserExtByAiId(aiId);
        output.setDialoguePrologue(aiUserExt != null ? aiUserExt.getDialoguePrologue() : "");
        //背景图
        output.setBackgroundImg(aiUser.getHomeImageUrl());
        return output;
    }

    @Override
    public AiUser getAiUserByAiId(Long aiId) {
        return getOne(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getAiId, aiId));
    }

    @Override
    public AiUserImBaseInfoOutput getAiUserImBaseInfo(Long aiId, Long userId) {
        //查询基础信息
        AiUser aiUser = getOne(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getAiId, aiId));
        ToastResultCode.AI_USER_NOT_EXIST.check(aiUser == null);
        //已经删除的，用户自己是不能看到的
        ToastResultCode.AI_USER_NOT_EXIST.check(aiUser.getIsDelete() && aiUser.getUserId().equals(userId));
        //已经删除的、私密的，只有有关系的人才能看到
        if (aiUser.getIsDelete() || (aiUser.getPermission() == 2 && !aiUser.getUserId().equals(userId))) {
            //判断是否存在关系
            boolean isRelation = aiUserHeartbeatRelationService.relationCheck(userId, aiId);
            ToastResultCode.AI_USER_NOT_EXIST.check(!isRelation);
        }
        AiUserImBaseInfoOutput output = BeanConver.copeBean(aiUser, AiUserImBaseInfoOutput.class);
        //性格，标签名称,角色名称
        Map<String, String> aiDictNameMap = aiDictService.mapNameByCodeList(Sets.newHashSet(aiUser.getRoleCode(), aiUser.getCharacterCode(), aiUser.getTagCode()));
        output.setCharacterName(aiDictNameMap.get(aiUser.getCharacterCode()));
        output.setTagName(aiDictNameMap.get(aiUser.getTagCode()));
        output.setRoleName(aiDictNameMap.get(aiUser.getRoleCode()));
        //被喜欢数
        output.setLikedNum(aiUserStatService.getAiLikedCount(aiId));
        //对话开场白放在扩展表中
        AiUserExt aiUserExt = aiUserExtService.getAiUserExtByAiId(aiId);
        output.setDialoguePrologue(aiUserExt.getDialoguePrologue());
        //用户与AI的心动关系
        output.setAiUserHeartbeatRelation(aiUserHeartbeatRelationService.getAiUserHeartbeatRelation(userId, aiId));
        //语音类型，音高，语速
        TimbreDict timbreDict = timbreDictService.getTimbreDictByCode(aiUserExt.getDialogueTimbreCode());
        output.setVoiceType(timbreDict != null ? timbreDict.getVoiceType() : null);
        output.setDialoguePitch(aiUserExt.getDialoguePitch());
        output.setDialogueSpeechRate(aiUserExt.getDialogueSpeechRate());
        //聊天设置相关
        ChatSet chatSet = chatSetService.getChatSet(userId, aiId);
        //聊天背景-默认主图
        String chatBackgroundImg = aiUser.getHomeImageUrl();
        if (chatSet != null) {
            //聊天设置相关-聊天背景 用户设置了用用户设置的背景，没有默认主图
            if (StringUtils.isNotEmpty(chatSet.getBackgroundImg()) && !chatSet.getBackgroundImg().equals(DEFAULT_BACKGROUND)) {
                chatBackgroundImg = chatSet.getBackgroundImg();
            }
            //聊天设置相关-是否自动播放语音
            output.setIsAutoPlayVoice(chatSet.getIsAutoPlayVoice());
            //聊天设置相关-是否删除聊天消息
            output.setIsDelChatted(chatSet.getIsDelChatted());
        }
        //聊天气泡
        String userSetBubbleCode = chatSet != null ? chatSet.getBubbleCode() : null;
        ChatBubbleDict chatBubbleDict = chatBubbleDictService.getUserChatBubble(userId, aiId, userSetBubbleCode);
        ChatBubbleOutput chatBubbleOutput = BeanConvert.copeBean(chatBubbleDict, ChatBubbleOutput.class);
        output.setChatBubble(chatBubbleOutput);
        //背景图
        output.setBackgroundImg(chatBackgroundImg);
        output.setIsDefaultBackground(chatBackgroundImg.equals(aiUser.getHomeImageUrl()));
        //是不是会员类型
        output.setIsMember(subscribeClient.queryUserIsSubscribe(userId));
        //获取当前用户是否点赞过
        if (userId != null) {
            output.setLiked(likedService.isLiked(userId, aiId, Liked.BizType.AI));
        }
        //判断是否已聊天过
        AiUserHeartbeatRelation aiUserHeartbeatRelation = aiUserHeartbeatRelationService.getHeartbeatRelation(userId, aiId);
        output.setIsHaveChatted(aiUserHeartbeatRelation != null);
        //发送MQ,计算一次用户与AI的心动分
        commonSendMqService.calcHeartbeatScoreMq(userId, aiId);
        return output;
    }

    @Override
    public Map<Long, AiUserBaseOutput> mapByAiIdList(List<Long> aiIdList) {
        if (CollectionUtils.isEmpty(aiIdList)) {
            return Collections.emptyMap();
        }
        //查询对应的AI用户信息
        List<AiUser> list = list(Wrappers.<AiUser>lambdaQuery()
                .in(AiUser::getAiId, aiIdList)
        );
        //获取字典数据
        Map<String, String> aiDictNameMap = mapNameByCodeList(list);
        List<AiUserBaseOutput> outputList = Lists.newArrayList();
        for (AiUser aiUser : list) {
            AiUserBaseOutput output = BeanConvert.copeBean(aiUser, AiUserBaseOutput.class);
            //组装字典数据
            output.setRoleName(aiDictNameMap.get(aiUser.getRoleCode()));
            output.setCharacterName(aiDictNameMap.get(aiUser.getCharacterCode()));
            output.setTagName(aiDictNameMap.get(aiUser.getTagCode()));
            outputList.add(output);
        }
        return outputList.stream().collect(Collectors.toMap(AiUserBaseOutput::getAiId, output -> output));
    }

    @Override
    public Integer countAiNumByUserId(Long userId) {
        return count(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getUserId, userId).eq(AiUser::getIsDelete, false));
    }

    @Override
    public AiUserSeoBaseInfoOutput getAiUserSeoBaseInfo(Long aiId) {
        AiUser aiUser = getOne(Wrappers.<AiUser>lambdaQuery().eq(AiUser::getAiId, aiId));
        AiUserSeoBaseInfoOutput output = new AiUserSeoBaseInfoOutput();
        output.setNickname(aiUser.getNickname());
        output.setHomeImageUrl(aiUser.getHomeImageUrl());
        return output;
    }
}