package cn.com.poc.common.service.impl;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import cn.com.gsst.dify_client.DifyChatClient;
import cn.com.gsst.dify_client.DifyClientFactory;
import cn.com.gsst.dify_client.callback.ChatStreamCallback;
import cn.com.gsst.dify_client.enums.FileTransferMethod;
import cn.com.gsst.dify_client.enums.FileType;
import cn.com.gsst.dify_client.enums.ResponseMode;
import cn.com.gsst.dify_client.event.MessageEndEvent;
import cn.com.gsst.dify_client.event.MessageEvent;
import cn.com.gsst.dify_client.exception.DifyApiException;
import cn.com.gsst.dify_client.model.DifyConfig;
import cn.com.gsst.dify_client.model.chat.ChatMessage;
import cn.com.gsst.dify_client.model.chat.ChatMessageResponse;
import cn.com.gsst.dify_client.model.file.FileInfo;
import cn.com.poc.agent_application.entity.AgentResultEntity;
import cn.com.poc.common.config.DifyConfigProperties;
import cn.com.poc.common.service.DifyChatService;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.SSEUtil;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelDemandResult;
import cn.com.yict.framemax.core.exception.BusinessException;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 通用Dify聊天服务，封装与Dify API交互的逻辑
 */
@Service
public class DifyChatServiceImpl implements DifyChatService {

    private final Logger logger = LoggerFactory.getLogger(DifyChatServiceImpl.class);

    private final String THINK_START_TAG = "<think>";

    private final String THINK_END_TAG = "</think>";

    @Autowired
    private DifyConfigProperties difyConfigProperties;

    /**
     * 阻塞式聊天请求
     *
     * @param fileUrls 文件地址
     * @param question 问题
     * @param data     拓展参数
     * @param user     用户
     * @param apiKey   API密钥
     */
    public AgentResultEntity blockingChat(List<String> fileUrls,
                                          String question,
                                          Map<String, Object> data,
                                          String user,
                                          String apiKey) {

        String actualApiKey = apiKey;
        if (StringUtils.isEmpty(actualApiKey)) {
            actualApiKey = difyConfigProperties.getApiKeys().get(user);
        }

        DifyConfig difyConfig = DifyConfig.builder()
                .apiKey(actualApiKey)
                .readTimeout(200 * 1000)
                .baseUrl(difyConfigProperties.getBaseUrl())
                .build();
        DifyChatClient chatClient = DifyClientFactory.createChatClient(difyConfig);

        List<FileInfo> files = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(fileUrls)) {
            for (String fileUrl : fileUrls) {
                files.add(FileInfo.builder()
                        .type(FileType.DOCUMENT)
                        .url(fileUrl)
                        .transferMethod(FileTransferMethod.REMOTE_URL)
                        .build());
            }
        }

        // 创建聊天消息
        ChatMessage chatMessage = ChatMessage.builder()
                .query(question)
                .user(user)
                .files(files)
                .inputs(data)
                .responseMode(ResponseMode.BLOCKING)
                .build();

        // 发送消息并获取响应
        try {
            ChatMessageResponse chatMessageResponse = chatClient.sendChatMessage(chatMessage);
            AgentResultEntity agentResultEntity = new AgentResultEntity();
            String answer = chatMessageResponse.getAnswer();

            int startIndex = answer.indexOf(THINK_START_TAG);
            int endIndex = answer.indexOf(THINK_END_TAG);

            if (startIndex != -1 && endIndex != -1 && endIndex > startIndex) {
                // 提取<think>标签内的内容
                String reasoningContent = answer.substring(startIndex + THINK_START_TAG.length(), endIndex);
                agentResultEntity.setReasoningContent(reasoningContent.trim());

                // 提取其余内容（去除<think>标签部分）
                String message = answer.substring(0, startIndex) + answer.substring(endIndex + THINK_END_TAG.length());
                agentResultEntity.setMessage(message);
            } else {
                // 如果没有找到<think>标签，将整个answer作为message
                agentResultEntity.setMessage(answer);
                agentResultEntity.setReasoningContent("");
            }

            return agentResultEntity;
        } catch (IOException | DifyApiException e) {
            logger.error("执行{}生成异常: {}", user, e.getMessage(), e);
            throw new BusinessException("执行" + user + "生成异常");
        }
    }

    /**
     * 流式聊天请求
     *
     * @param fileUrls 文件地址
     * @param question 问题
     * @param data     拓展参数
     * @param user     用户
     * @param apiKey   API密钥
     */
    public AgentResultEntity streamChat(List<String> fileUrls,
                                        String question,
                                        Map<String, Object> data,
                                        String user,
                                        String apiKey) {
        AgentResultEntity agentResultEntity = new AgentResultEntity();

        StringBuilder messageBuilder = new StringBuilder();
        StringBuilder reasoningContentBuilder = new StringBuilder();
        // 从配置中获取API密钥，如果传入的apiKey为null或空，则从配置中查找
        String actualApiKey = apiKey;
        if (StringUtils.isEmpty(actualApiKey)) {
            actualApiKey = difyConfigProperties.getApiKeys().get(user);
        }

        // 创建聊天客户端
        DifyChatClient chatClient =
                DifyClientFactory.createChatWorkflowClient(difyConfigProperties.getBaseUrl(), actualApiKey);

        List<FileInfo> files = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(fileUrls)) {
            for (String fileUrl : fileUrls) {
                files.add(FileInfo.builder()
                        .type(FileType.DOCUMENT)
                        .url(fileUrl)
                        .transferMethod(FileTransferMethod.REMOTE_URL)
                        .build());
            }
        }

        // 创建聊天消息
        ChatMessage message = ChatMessage.builder()
                .query(question)
                .user(user)
                .files(files)
                .inputs(data)
                .responseMode(ResponseMode.STREAMING)
                .build();

        CountDownLatch countDownLatch = new CountDownLatch(1);
        ServletRequestAttributes servletRequestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();

        // 发送消息并获取响应
        try {
            chatClient.sendChatMessageStream(message, new ChatStreamCallback() {
                SSEUtil sseUtil = new SSEUtil(response);

                boolean isThink = false;

                /**
                 * 解析深度思考文本内容
                 * 处理思考标记的开始和结束标签，提取纯文本内容
                 *
                 * @param content 原始内容
                 * @return 解析后的文本内容，如果内容不完整则返回空字符串
                 */
                String parseDeepThinkingContent(String content) {
                    if (!isThink) {
                        if (content.contains(THINK_START_TAG)) {
                            isThink = true;
                            return content.replaceFirst(THINK_START_TAG, StringUtils.EMPTY);
                        }
                        return content;
                    } else {
                        if (content.contains(THINK_END_TAG)) {
                            isThink = false;
                            return content.replaceFirst(THINK_END_TAG, StringUtils.EMPTY);
                        }
                        return StringUtils.EMPTY;
                    }
                }

                void responseMess(MessageEvent event) throws IOException {
                    if (StringUtils.isNotEmpty(event.getAnswer())) {
                        String think = parseDeepThinkingContent(event.getAnswer());
                        LargeModelDemandResult largeModelDemandResult = new LargeModelDemandResult();
                        if (isThink || StringUtils.isNotBlank(think)) {
                            largeModelDemandResult.setReasoningContent(think);
                            reasoningContentBuilder.append(think);
                        } else if (!isThink || StringUtils.isNotBlank(think)) {
                            largeModelDemandResult.setMessage(think);
                            reasoningContentBuilder.append(think);
                        } else {
                            largeModelDemandResult.setMessage(event.getAnswer());
                            messageBuilder.append(event.getAnswer());
                        }
                        largeModelDemandResult.setCode("0");
                        sseUtil.send(JsonUtils.serialize(largeModelDemandResult));
                    }
                }

                @Override
                public void onMessage(MessageEvent event) {
                    try {
                        responseMess(event);
                    } catch (Exception e) {
                        logger.error("发送SSE消息时出错: {}", e.getMessage(), e);
                        sseUtil.completeByError(e.getMessage());
                        throw new RuntimeException(e);
                    }
                }

                @Override
                public void onMessageEnd(MessageEndEvent event) {
                    try {
                        sseUtil.send("[DONE]");
                    } catch (IOException e) {
                        logger.error("发送SSE结束消息时出错: {}", e.getMessage(), e);
                        sseUtil.completeByError(e.getMessage());
                        throw new RuntimeException(e);
                    } finally {
                        sseUtil.complete();
                        agentResultEntity.setMessage(messageBuilder.toString());
                        agentResultEntity.setReasoningContent(reasoningContentBuilder.toString());
                    }
                    countDownLatch.countDown();
                }

            });
            countDownLatch.await(120, TimeUnit.SECONDS);
            return agentResultEntity;
        } catch (Exception e) {
            countDownLatch.notify();
            SSEUtil sseUtil = new SSEUtil(response);
            sseUtil.completeByError(e.getMessage());
            throw new BusinessException(e.getMessage());
        }
    }

}