package com.seer.teach.teacher.processor.chat;

import cn.hutool.json.JSONUtil;
import com.seer.teach.common.cache.LlmAudioPublisherService;
import com.seer.teach.common.dto.mq.LlmChatDTO;
import com.seer.teach.common.dto.mq.StringDTO;
import com.seer.teach.common.enums.im.ImMqTopicEnum;
import com.seer.teach.common.enums.im.RedisChannelPushTopTagEnum;
import com.seer.teach.teacher.common.llm.sse.req.LlmSseChatReq;
import com.seer.teach.teacher.common.utils.TeacherUtils;
import com.seer.teach.teacher.common.utils.UserQuestionTextCache;
import com.seer.teach.teacher.mq.ImMqProducer;
import com.seer.teach.teacher.processor.base.AbstractStreamProcessor;
import com.seer.teach.teacher.service.ChatLogsService;
import com.seer.teach.teacher.service.LlmSseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.Disposable;
import reactor.core.publisher.Flux;

@Slf4j
@Component
@RequiredArgsConstructor
public class SseAudioStreamProcessor extends AbstractStreamProcessor<LlmSseChatReq, LlmChatDTO, String> {

    private final LlmAudioPublisherService llmAudioPublisherService;

    private final UserQuestionTextCache userQuestionTextCache;

    private final ChatLogsService chatLogsService;

    private final LlmSseService llmSseService;

    private final ImMqProducer imMqProducer;

    @Override
    protected void onBeforeStart(Integer userId, LlmSseChatReq llmSseChatReq, String device, Flux<LlmChatDTO> flux, String channelName) {
        imMqProducer.sendAudioChannelName(device,channelName);
    }

    @Override
    protected void onStart(Integer userId, LlmSseChatReq llmSseChatReq, String s) {

    }

    @Override
    protected void onData(Integer userId, String device, LlmChatDTO data, String channelName) {
        data.setMqTime(System.currentTimeMillis());
        llmAudioPublisherService.publishToDevice(channelName, data);

        // 如果是最终结果，保存聊天日志
        if (data.getIsFinal()) {
            String userQuestion = userQuestionTextCache.poll(userId);
            chatLogsService.saveChatLog(userQuestion, data.getAllText(), userId);
        }
    }

    @Override
    protected void onError(Integer userId, String device, String channelName, Throwable error) {
        log.error("Llm 流式返回异常: userId={}, device={}, error={}", userId, device, error.getMessage(), error);
        // 向客户端推送LLM音频错误消息
        imMqProducer.sendMsg(
                ImMqTopicEnum.REDIS_CHANNEL_PUSH,
                RedisChannelPushTopTagEnum.PUSH_LLM_AUDIO_ERROR.getTag(),
                device,
                JSONUtil.toJsonStr(new StringDTO(channelName))
        );
    }

    @Override
    protected void onRegister(Integer userId, Disposable disposable) {
        llmSseService.registerStream(userId, TeacherUtils.SSE_TYPE_CHAT, disposable);
    }
}