package com.easyproject.system.service.chatAI.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.coze.openapi.client.chat.CreateChatReq;
import com.coze.openapi.client.chat.model.ChatEvent;
import com.coze.openapi.client.chat.model.ChatEventType;
import com.coze.openapi.client.connversations.message.model.Message;
import com.coze.openapi.service.service.CozeAPI;
import com.easyproject.common.utils.coze.ChatAiForCozeUtils;
import com.easyproject.service.domain.coze.CozeBotSet;
import com.easyproject.service.domain.coze.CozeTokenSet;
import com.easyproject.service.domain.coze.CozeWorkspacesSet;
import com.easyproject.service.mapper.coze.CozeBotSetMapper;
import com.easyproject.service.mapper.coze.CozeTokenSetMapper;
import com.easyproject.service.mapper.coze.CozeWorkspacesSetMapper;
import com.easyproject.service.service.ICozeJwtService;
import com.easyproject.system.service.chatAI.IChatAIService;
import io.reactivex.Flowable;
import io.reactivex.schedulers.Schedulers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;

import javax.annotation.Resource;
import java.util.Collections;

/**
 * 方法说明: 聊天验证
 * @param
 * @return
 * @author java-101
 * @date 2025-03-12 23:21:37
 */
@Slf4j
@Service
public class ChatAIServiceImpl implements IChatAIService {

    @Resource
    private CozeWorkspacesSetMapper cozeWorkspacesSetMapper;
    @Resource
    private CozeBotSetMapper cozeBotSetMapper;
    @Resource
    private ICozeJwtService cozeJwtService;

    //随机用户ID
    private String userID = UUID.randomUUID().toString();

    /**
     * 方法说明: 发起消息-通过流式返回-coze平台
     * @param message 用户输入的消息
     * @param conversationId 会话ID
     * @return 流式返回的消息
     * @author java-101
     * @date 2025-03-12 23:23:23
     */
    @Override
    public Flux<String> chatStream(String message,String conversationId) {
        // 查询系统token 使用JWT方式获取token（永久授权）
        CozeTokenSet tokenSet = cozeJwtService.getCozeTokenSetForToken();
        if(ObjectUtil.isEmpty(tokenSet)){
            log.error("token为空，请先设置token！");
            return Flux.error(new RuntimeException("token为空，系统错误，稍后重试"));
        }

        //查询有效空间
        CozeWorkspacesSet workspacesSet = cozeWorkspacesSetMapper.selectOne(Wrappers.<CozeWorkspacesSet>lambdaQuery().eq(CozeWorkspacesSet::getStatus,1).orderByDesc(CozeWorkspacesSet::getId).last("limit 1"));
        if(ObjectUtil.isEmpty(workspacesSet)){
            log.error("系统错误，请稍后重试");
            return Flux.error(new RuntimeException("系统错误，请稍后重试"));
        }
        //查询机器人ID（智能体ID）
        CozeBotSet botSet = cozeBotSetMapper.selectOne(Wrappers.<CozeBotSet>lambdaQuery().eq(CozeBotSet::getStatus,1).eq(CozeBotSet::getSpaceId,workspacesSet.getSpacesId()).orderByDesc(CozeBotSet::getId).last("limit 1"));
        if(ObjectUtil.isEmpty(botSet)){
            log.error("系统错误，请稍后重试");
            return Flux.error(new RuntimeException("系统错误，请稍后重试"));
        }


        //初始化客户端
        CozeAPI coze = ChatAiForCozeUtils.getCozeClient(tokenSet.getPersonToken());

        // 处理流式返回数据
        Sinks.Many<String> sink = Sinks.many().unicast().onBackpressureBuffer();
        CreateChatReq req = null;
        if(ObjectUtil.isEmpty(conversationId)||conversationId.equals("null")){
            req = CreateChatReq.builder()
                    .botID(botSet.getBotId())
                    .userID(userID)
                    .messages(Collections.singletonList(Message.buildUserQuestionText(message)))
                    .build();
        }else{
            // 构造聊天请求
            req = CreateChatReq.builder()
                    .botID(botSet.getBotId())
                    .userID(userID)
                    .conversationID(conversationId)
                    .messages(Collections.singletonList(Message.buildUserQuestionText(message)))
                    .build();

        }

        Flowable<ChatEvent> response = coze.chat().stream(req);
        response.subscribeOn(Schedulers.io()).subscribe(
                event -> {
                    if (ChatEventType.CONVERSATION_CHAT_CREATED.equals(event.getEvent())) {
                        //log.info("会话开始：{} - {}", event.getChat().getConversationID(),event.getChat().getID());
                        String eventJson = JSONUtil.toJsonStr(event);
                        sink.tryEmitNext(eventJson);
                    }
                    if (ChatEventType.CONVERSATION_MESSAGE_DELTA.equals(event.getEvent())) {
                        String eventJson = JSONUtil.toJsonStr(event);
                        sink.tryEmitNext(eventJson);
                    }
                    if (ChatEventType.CONVERSATION_CHAT_COMPLETED.equals(event.getEvent())) {
                        String eventJson = JSONUtil.toJsonStr(event);
                        sink.tryEmitNext(eventJson);
                        sink.tryEmitComplete();
                    }
                },
                error -> sink.tryEmitError(error)
        );
        return sink.asFlux();
    }

}
