package com.sonic.cow.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.byteplus.ark.runtime.model.completion.chat.ChatMessageRole;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
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.request.Tools;
import com.sonic.cow.client.response.ResponseChatResponse;
import com.sonic.cow.domain.entity.PromptConfig;
import com.sonic.cow.enums.DeductionTypeEnum;
import com.sonic.cow.enums.PromptTypeEnum;
import com.sonic.cow.event.outer.payload.AiChatPayload;
import com.sonic.cow.event.outer.payload.CalcHeartbeatLevelPayload;
import com.sonic.cow.event.outer.payload.UserDeductionStatPayload;
import com.sonic.cow.service.*;
import com.sonic.cow.tools.GetAiImageArgs;
import com.sonic.cow.tools.ToolsDefinition;
import com.sonic.cow.utils.RedisKeyUtils;
import com.sonic.frog.lib.output.AIUserAlbumApiOutput;
import com.sonic.pigeon.lib.bo.AttachBo;
import com.sonic.pigeon.lib.bo.ScoreExtension;
import com.sonic.pigeon.lib.client.ImMessageClient;
import com.sonic.pigeon.lib.enums.MessageTypeEnum;
import com.sonic.pigeon.lib.input.SendAiCustomerMessageInput;
import com.sonic.pigeon.lib.input.SendAiTextMessageInput;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
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.HashMap;
import java.util.List;

@Slf4j
@Service
public class ChatHandlerServiceImpl implements ChatHandlerService {

    @Autowired
    private ContextSessionCacheService contextSessionCacheService;
    @Autowired
    private ImMessageClient imMessageClient;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private ResponseChatClient responseChatClient;
    @Autowired
    private RedisKeyUtils redisKeyUtils;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private InputRequestBuildService inputRequestBuildService;
    @Autowired
    private FunctionCallService functionCallService;
    @Autowired
    private PromptConfigService promptConfigService;

    @Override
    public void handle(AiChatPayload payload, AttachBo attachBo) {
        //获取上下文缓存
        String responseId = contextSessionCacheService.getByRedis(payload.getFromUserId(), payload.getToUserId());
        log.info("===> AiChatHandler content : {}, responseId : {}", payload.getContent(), responseId);
        //组装出消息列表数据
        List<InputRequest> inputRequests = Lists.newArrayList();
        //获取历史上下文，创建上下文缓存
        if (StringUtils.isEmpty(responseId)) {
            inputRequestBuildService.buildV2(payload, inputRequests,100,true);
        }
        log.info("===> AiChatHandler responseId : {}", responseId);
        long startTime = System.currentTimeMillis();
        if(MessageTypeEnum.CUSTOM == payload.getMessageType() && attachBo != null && "IMAGE".equalsIgnoreCase(attachBo.getType()) && StringUtils.isNotBlank(attachBo.getUrl())) {
            //图片加尺寸
            inputRequests.add(InputRequest.builder()
                    .role(ChatMessageRole.USER)
                    .content(Lists.newArrayList(ContentRequest.builder().type("input_text").text(payload.getContent()).build(),
                            ContentRequest.builder().type("input_image").imageUrl(attachBo.getUrl() + "?x-oss-process=image/resize,w_200,h_200").build()))
                    .build());
        } else {
            inputRequests.add(InputRequest.builder()
                    .role(ChatMessageRole.USER)
                    .content(Lists.newArrayList(ContentRequest.builder().type("input_text").text(payload.getContent()).build()))
                    .build());
        }

        //获取图片
        PromptConfig systemPromptConfig = promptConfigService.getPromptTemplate(PromptTypeEnum.GET_AI_IMAGE_FUNCTION_CALL.name());
        List<Tools> tools = Lists.newArrayList(ToolsDefinition.getAiImageToolsV2("get_ai_image", systemPromptConfig.getPromptTemplate()));
        GetAiImageArgs getAiImageArgs = GetAiImageArgs.builder()
                .userId(payload.getFromUserId())
                .aiId(payload.getToUserId())
                .build();
        //上下文聊天
        ResponseChatResponse chatResponse = responseChatClient.responseStructuredChat(responseId, null, inputRequests, tools, JSONObject.toJSONString(getAiImageArgs), null, null);
        log.info("===> chatResponse : {}", chatResponse);
        if(chatResponse == null) {
            return;
        }
        //异常码判断
        if(chatResponse.getCode() != null) {
            //根据异常码判断处理redis数据删除
            if("InvalidParameter.PreviousResponseNotFound".equalsIgnoreCase(chatResponse.getCode())) {
                contextSessionCacheService.deleteRedis(payload.getFromUserId(), payload.getToUserId());
                return;
            }
        }

        log.info("===> AiChatHandler chat time : {} ms", System.currentTimeMillis() - startTime);
        //处理方法回调
        if(chatResponse.getFunctionCallName() != null && chatResponse.getFunctionCallArguments() != null) {
            //RPC 获取图片 并发送
            AIUserAlbumApiOutput album = functionCallService.callFunction(chatResponse);
            //有回调ID的时候才进行回调
            if(StringUtils.isNotEmpty(chatResponse.getFunctionCallId())) {
                //工具调用后反馈调用聊天
                chatResponse = functionCallFeedbackChat(responseId, inputRequests, chatResponse, album);
            } else {
                if(album == null) {
                    chatResponse.setMessage("Go check out my photo album");
                } else {
                    chatResponse.setMessage("This is my photo; you need to unlock it to view it");
                }
            }
            if(album == null) {
                //发送文本IM消息
                sendImMessage(payload, chatResponse);
            } else {
                //发送自定义Im消息
                sendImCustomMessage(payload, chatResponse.getMessage(), album, chatResponse);
            }
        } else {
            //发送IM消息
            sendImMessage(payload, chatResponse);
        }
        //是否存在清理缓存的任务数据
        boolean hasKey = stringRedisTemplate.hasKey(redisKeyUtils.chatResponseIdClearTaskKey(payload.getFromUserId(), payload.getToUserId()));
        if(hasKey) {
            //清理掉缓存数据
            contextSessionCacheService.deleteRedis(payload.getFromUserId(), payload.getToUserId());
            //删除掉任务数据
            stringRedisTemplate.delete(redisKeyUtils.chatResponseIdClearTaskKey(payload.getFromUserId(), payload.getToUserId()));
        } else {
            //将缓存id更新到缓存中去，过期时间3天
            if(StringUtils.isNotEmpty(chatResponse.getResponseId())) {
                contextSessionCacheService.saveToRedis(payload.getFromUserId(), payload.getToUserId(), chatResponse.getResponseId());
            }
        }
        //记录到redis中，24小时后会主动给用户发送一条消息
        String ftUserId = payload.getFromUserId() + "-" + payload.getToUserId();
        stringRedisTemplate.opsForZSet().add(redisKeyUtils.notifyUserZSetKey(), ftUserId, System.currentTimeMillis() / 1000);

        //发送MQ计算心动等级
        commonSendMqService.calHeartbeatLevelSendMq(CalcHeartbeatLevelPayload.builder()
                .userId(payload.getFromUserId())
                .aiId(payload.getToUserId())
                .heartbeatVal(chatResponse.getScore() == null ? new BigDecimal(0) : chatResponse.getScore())
                .type(CalcHeartbeatLevelPayload.Type.CHAT)
                .build());
        //发送用户文本预扣费统计
        HashMap<Object, Object> extraMap = Maps.newHashMap();
        extraMap.put("userContent", payload.getContent());
        extraMap.put("aiContent", chatResponse.getMessage());
        commonSendMqService.userDeductionStatSendMq(UserDeductionStatPayload.builder()
                .userId(payload.getFromUserId())
                .aiId(payload.getToUserId())
                .deductionType(DeductionTypeEnum.TEXT)
                .bizTime(LocalDateTime.now())
                .extra(JSON.toJSONString(extraMap))
                .build());
    }

    /**
     * 函数调用反馈
     * @param responseId
     * @param inputRequests
     * @param chatResponse
     * @param album
     */
    private ResponseChatResponse functionCallFeedbackChat(String responseId, List<InputRequest> inputRequests, ResponseChatResponse chatResponse, AIUserAlbumApiOutput album) {
        //TODO 获取图片来决定回什么内容
        //组装出消息列表数据
        inputRequests.add(InputRequest.builder()
                .callId(chatResponse.getFunctionCallId())
                        .name(chatResponse.getFunctionCallName())
                        .arguments(chatResponse.getFunctionCallArguments())
                        .type("function_call")
                .build());
        inputRequests.add(InputRequest.builder()
                .callId(chatResponse.getFunctionCallId())
                .output(album != null ? "This is my photo; you need to unlock it to view it" : "Go check out my photo album")
                .type("function_call_output")
                .build());

        //上下文聊天
        return responseChatClient.responseStructuredChat(responseId, null, inputRequests, null, null, null, null);
    }

    /**
     * 发送Im消息
     * @param payload
     * @param chatResponse
     */
    private void sendImMessage(AiChatPayload payload, ResponseChatResponse chatResponse) {
        if(chatResponse == null || StringUtils.isEmpty(chatResponse.getMessage())) {
            return;
        }
        // 发送消息给用户
        SendAiTextMessageInput sendAiTextMessageInput = new SendAiTextMessageInput();
        sendAiTextMessageInput.setFromUserId(payload.getToUserId());
        sendAiTextMessageInput.setToUserId(payload.getFromUserId());
        sendAiTextMessageInput.setContent(chatResponse.getMessage());
        //在扩展字段中 增加一个分值字段来进行处理
        sendAiTextMessageInput.setExtension(chatResponse.getScore() == null ? null : JSONObject.toJSONString(ScoreExtension.builder().score(chatResponse.getScore()).build()));
        imMessageClient.sendAiToUserTextMessage(sendAiTextMessageInput);
    }

    /**
     * 发送Im消息
     * @param payload
     * @param album
     * @param chatResponse
     */
    @Override
    public void sendImCustomMessage(AiChatPayload payload, String message, AIUserAlbumApiOutput album, ResponseChatResponse chatResponse) {
        if(chatResponse == null || StringUtils.isEmpty(chatResponse.getMessage())) {
            return;
        }
        //图片地址不为空则发送图片的自定义IM消息
        SendAiCustomerMessageInput sendAiCustomerMessageInput = new SendAiCustomerMessageInput();
        sendAiCustomerMessageInput.setFromUserId(payload.getToUserId());
        sendAiCustomerMessageInput.setToUserId(payload.getFromUserId());
        sendAiCustomerMessageInput.setContent(message);
        if(album != null) {
            sendAiCustomerMessageInput.setAttachment(JSONObject.toJSONString(AttachBo.builder()
                            .type("IMAGE")
                            .height("2560")
                            .width("1440")
                            .unlockPrice(album.getUnlockPrice())
                            .albumId(album.getAlbumId())
                            .url(album.getImgUrl())
                    .build())
            );
        }
        //在扩展字段中 增加一个分值字段来进行处理
        sendAiCustomerMessageInput.setExtension(chatResponse.getScore() == null ? null : JSONObject.toJSONString(ScoreExtension.builder().score(chatResponse.getScore()).build()));
        imMessageClient.sendAiToUserCustomerMessage(sendAiCustomerMessageInput);
    }

}
