package com.sonic.cow.event.inner.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.byteplus.ark.runtime.model.completion.chat.ChatMessage;
import com.byteplus.ark.runtime.model.completion.chat.ChatMessageRole;
import com.google.common.collect.Lists;
import com.sonic.common.event.Event;
import com.sonic.common.event.EventConsumer;
import com.sonic.common.event.EventHandler;
import com.sonic.cow.client.ResponseChatClient;
import com.sonic.cow.client.request.ContentRequest;
import com.sonic.cow.client.request.InputRequest;
import com.sonic.cow.client.response.ResponseChatResponse;
import com.sonic.cow.event.inner.EventType;
import com.sonic.cow.event.inner.payload.EmotionScorePayload;
import com.sonic.cow.event.outer.payload.AiChatPayload;
import com.sonic.cow.event.outer.payload.CalcHeartbeatLevelPayload;
import com.sonic.cow.service.CommonSendMqService;
import com.sonic.cow.service.ContextSessionCacheService;
import com.sonic.cow.service.InputRequestBuildService;
import com.sonic.cow.service.VoiceChatService;
import com.sonic.cow.utils.RedisKeyUtils;
import com.sonic.pigeon.lib.bo.ScoreExtension;
import com.sonic.pigeon.lib.client.ImMessageClient;
import com.sonic.pigeon.lib.input.SendAiCustomerMessageInput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;


/**
 * @author chenjun
 */
@Slf4j
@Component
public class VoiceCallEmotionScoreHandler implements EventHandler, InitializingBean {

    @Autowired
    private EventConsumer eventConsumer;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private ImMessageClient imMessageClient;
    @Autowired
    private RedisKeyUtils redisKeyUtils;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ContextSessionCacheService contextSessionCacheService;
    @Autowired
    private InputRequestBuildService inputRequestBuildService;
    @Autowired
    private ResponseChatClient responseChatClient;
    @Autowired
    private VoiceChatService voiceChatService;

    @Override
    public void onEvent(Event event) {
        EmotionScorePayload payload = event.normalizedData(EmotionScorePayload.class);
        log.info("EmotionScoreHandler payload:{}", payload);
        Long userId = payload.getUserId();
        Long aiId = payload.getAiId();
        List<ChatMessage> chatMessageList = payload.getChatMessageList();
        //对话消息要成对才执行情绪打分
        if (CollectionUtils.isNotEmpty(chatMessageList) && chatMessageList.size() > 1) {
            BigDecimal voiceCallEmotionScore = getVoiceCallEmotionScore(userId, aiId, chatMessageList);

            if (voiceCallEmotionScore != null) {
                log.info("===>EmotionScoreHandler score: {}", voiceCallEmotionScore);
                //发送MQ进行等级结算
                commonSendMqService.calHeartbeatLevelSendMq(CalcHeartbeatLevelPayload.builder()
                        .userId(userId)
                        .aiId(aiId)
                        .heartbeatVal(voiceCallEmotionScore)
                        .type(CalcHeartbeatLevelPayload.Type.VOICE_CHAT)
                        .build());
                //发送IM消息更新心动值
                SendAiCustomerMessageInput sendAiCustomerMessageInput = new SendAiCustomerMessageInput();
                sendAiCustomerMessageInput.setFromUserId(aiId);
                sendAiCustomerMessageInput.setToUserId(userId);
                sendAiCustomerMessageInput.setContent("语音通话");
                sendAiCustomerMessageInput.setAttachment(JSONObject.toJSONString(ScoreExtension.builder().score(voiceCallEmotionScore).build()));
                sendAiCustomerMessageInput.setExtension(JSONObject.toJSONString(ScoreExtension.builder().score(voiceCallEmotionScore).build()));
                imMessageClient.sendAiToUserCustomerMessage(sendAiCustomerMessageInput);
            }
        }
        Boolean isEnd = payload.getIsEnd();
        if (!isEnd) {
            //缓存每轮对话内容
            cacheAndGetVoiceChatInputRequests(userId, aiId, chatMessageList, isEnd);
        } else {
            //通话结束时,获取缓存中本次语音通话所有内容
            List<InputRequest> voiceChatInputRequestList = cacheAndGetVoiceChatInputRequests(userId, aiId, chatMessageList, isEnd);
            log.info("===>EmotionScoreHandler voiceChatInputRequestList:{}", JSON.toJSONString(voiceChatInputRequestList));
            //语音通话结束处理
            voiceChatService.voiceCallEndHandler(userId, aiId, voiceChatInputRequestList, payload.getDuration());
        }
    }

    @Override
    public void afterPropertiesSet() {
        eventConsumer.registerHandler(EventType.EMOTION_SCORE.getEventCode(), this);
    }

    /**
     * 语音通话情绪打分
     *
     * @param fromUserId
     * @param toUserId
     * @return
     */
    private BigDecimal getVoiceCallEmotionScore(Long fromUserId, Long toUserId, List<ChatMessage> messages) {
        //获取上下文缓存 这个缓存一定是存在的
        String responseId = contextSessionCacheService.getByRedis(fromUserId, toUserId);
        List<InputRequest> inputRequests = Lists.newArrayList();
        if (StringUtils.isEmpty(responseId)) {
            AiChatPayload payload = AiChatPayload.builder().fromUserId(fromUserId).toUserId(toUserId).build();
            //调用公共方法，组装入参数据
            inputRequestBuildService.buildV2(payload, inputRequests, 30, false);
        }
        //构造系统提示词
        String emotionScorePrompt = inputRequestBuildService.buildVoiceCallEmotionScorePromptContent(JSON.toJSONString(messages));
        inputRequests.add(InputRequest.builder()
                .role(ChatMessageRole.SYSTEM)
                .content(Lists.newArrayList(ContentRequest.builder().type("input_text").text(emotionScorePrompt).build())).build());
        //执行聊天 不将添加缓存
        ResponseChatResponse chatResponse = responseChatClient.responseStructuredChat(responseId, null, inputRequests, null, false);
        log.info("===> getVoiceCallEmotionScore chatResponse : {}", chatResponse);
        if (chatResponse != null && chatResponse.getScore() != null) {
            return chatResponse.getScore();
        }
        return BigDecimal.ZERO;
    }

    private List<InputRequest> cacheAndGetVoiceChatInputRequests(Long userId, Long aiId, List<ChatMessage> messages, Boolean isEnd) {
        //不是成对的，不记录
        if (messages.size() % 2 != 0) {
            return null;
        }
        List<InputRequest> inputRequestList = Lists.newArrayList();
        String voiceChatMessageCacheKey = redisKeyUtils.voiceChatMessageCacheKey(userId, aiId);
        String voiceChatMessageStr = stringRedisTemplate.opsForValue().get(voiceChatMessageCacheKey);
        for (ChatMessage message : messages) {
            inputRequestList.add(InputRequest.builder()
                    .type("message")
                    .role(message.getRole())
                    .content(Lists.newArrayList(ContentRequest.builder().type("input_text").text(message.getContent().toString()).build()))
                    .build());
        }
        if (StringUtils.isNotEmpty(voiceChatMessageStr)) {
            //之前有的话，先拿出来，再添加放到缓存中
            List<InputRequest> oldInputRequestList = JSON.parseArray(voiceChatMessageStr, InputRequest.class);
            oldInputRequestList.addAll(inputRequestList);
            //赋值到新的
            inputRequestList = oldInputRequestList;
        }
        if (!isEnd) {
            //通话未结束，要缓存
            stringRedisTemplate.opsForValue().set(voiceChatMessageCacheKey, JSON.toJSONString(inputRequestList));
        } else {
            //通话结束，要删除
            stringRedisTemplate.delete(voiceChatMessageCacheKey);
        }
        return inputRequestList;
    }

    /**
     * 余额不足时，获取语音通话中的聊天内容
     * @param userId
     * @param aiId
     * @return
     */
    public List<InputRequest> getVoiceChatInputRequests(Long userId, Long aiId) {
        List<InputRequest> inputRequestList = Lists.newArrayList();
        String voiceChatMessageCacheKey = redisKeyUtils.voiceChatMessageCacheKey(userId, aiId);
        String voiceChatMessageStr = stringRedisTemplate.opsForValue().get(voiceChatMessageCacheKey);
        if (StringUtils.isNotEmpty(voiceChatMessageStr)) {
            return JSON.parseArray(voiceChatMessageStr, InputRequest.class);
        }
        return inputRequestList;
    }
}
