package cn.com.poc.ai_software_copyright.agent;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
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.ai_software_copyright.contant.AiSoftWareCopyRightEnum;
import cn.com.poc.ai_software_copyright.contant.AiSoftWareCopyRightRedisKey;
import cn.com.poc.ai_software_copyright.domain.GeneratedDoc;
import cn.com.poc.ai_software_copyright.domian.BaseInfo;
import cn.com.poc.ai_software_copyright.domian.TechnicalContent;
import cn.com.poc.common.pool.CommonThreadPoolExecutor;
import cn.com.poc.common.utils.DateUtils;
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.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author alex.yao
 * @date 2025/12/29
 */
@Component
public class SoftwareCopyRightAgent {

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

    @Value("${dify.base.url}")
    private String DIFY_BASE_URL;

    @Value("${dify.software_copyright.callball.url}")
    private String CALL_BACK_URL;

    /**
     * 软著AI助手
     */
    public void softwareCopyRightAssistant(List<String> fileUrls, String question, Map<String, Object> data)
            throws DifyApiException, IOException, InterruptedException {
        String API_KEY = "app-S3y8vmyX95cTa0sb9V9oBfSX";
        streamChat(
                fileUrls,
                question,
                data,
                AiSoftWareCopyRightEnum.AI_ASSISTANT_TYPE.DEVELOPMENT_PURPOSE.name(),
                API_KEY
        );
    }

    /**
     * 生成基础文档
     *
     * @param taskId
     * @param files
     * @param baseInfo
     * @param technicalContent
     */
    public void generatedBaseDoc(String taskId, List<String> files, BaseInfo baseInfo,
                                 TechnicalContent technicalContent) {
        String api_key = "app-VgynqQ7MDYW6CjUbtDu4osBf";
        String ques = "执行";
        String user = "generatedBaseDoc" + DateUtils.getCurrTime();

        Map<String, Object> data = new HashMap<>();
        data.put("task_id", taskId);
        data.put("baseinfo", JsonUtils.serialize(baseInfo));
        data.put("technical_content", JsonUtils.serialize(technicalContent));
        data.put("callback_url", CALL_BACK_URL);
        CommonThreadPoolExecutor.addTask(() -> blockingChat(files, ques, data, user, api_key));
    }


    /**
     * 文件生成
     *
     * @param generatedDoc
     * @param docType
     * @return
     */
    public void generatedDocByType(GeneratedDoc generatedDoc, AiSoftWareCopyRightEnum.DOC_TYPE docType) {
        switch (docType) {
            case source_code:
                sourceCode(generatedDoc);
                break;
            case ph_operating_manual:
                phOperatingManual(generatedDoc);
                break;
            case pc_operating_manual:
                pcOperatingManual(generatedDoc);
                break;
            case information:
                information(generatedDoc);
                break;
            default:
                throw new BusinessException("不支持的文档类型：" + docType);
        }
    }

    /**
     * 软著AI助手-技术内容生成
     *
     * @param fileUrls
     * @param query
     * @param data     - files 除源代码以外的文档内容 / code - 源代码
     * @return
     */
    public String technicalContent(List<String> fileUrls, String query, Map<String, Object> data) {

        DifyChatClient chatClient = DifyClientFactory.createChatClient(DIFY_BASE_URL, "app-VuwhZGr7UqFb2gkg7jOmibGM");

        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(query)
                .user("user-technicalContent")
                .files(files)
                .inputs(data)
                .responseMode(ResponseMode.BLOCKING)
                .build();

        // 发送消息并获取响应
        try {
            ChatMessageResponse chatMessageResponse = chatClient.sendChatMessage(message);
            return chatMessageResponse.getAnswer();
        } catch (IOException | DifyApiException e) {
            throw new BusinessException("执行【技术内容】生成异常");
        }
    }

    // 软著AI助手-源代码生成
    private void sourceCode(GeneratedDoc doc) {
        String api_key = "app-c0PWYmcythg7bIVxvt4d4kDM";
        String q = "生成源代码";
        Map<String, Object> data = new HashMap<>();
        data.put("ui", doc.getUi());
        data.put("structure", doc.getStructure());
        data.put("demand", doc.getDemand());
        data.put("code", "");
        data.put("baseinfo", JsonUtils.serialize(doc.getBaseinfo()));
        data.put("technical_content", JsonUtils.serialize(doc.getTechnical_content()));
        data.put("callback_url", CALL_BACK_URL);
        data.put("task_id", AiSoftWareCopyRightRedisKey.CALL_BACK + doc.getId());
        String user = "phOperatingManual" + DateUtils.getCurrTime();
        CommonThreadPoolExecutor.addTask(() -> blockingChat(doc.getFileURLs(), q, data, user, api_key));
    }

    // 软著AI助手-手机端说明书
    private void phOperatingManual(GeneratedDoc doc) {
        String api_key = "app-c0PWYmcythg7bIVxvt4d4kDM";
        String q = "生成手机端使用说明书";
        Map<String, Object> data = new HashMap<>();
        data.put("ui", doc.getUi());
        data.put("structure", doc.getStructure());
        data.put("demand", doc.getDemand());
        data.put("code", "");
        data.put("baseinfo", JsonUtils.serialize(doc.getBaseinfo()));
        data.put("technical_content", JsonUtils.serialize(doc.getTechnical_content()));
        data.put("callback_url", CALL_BACK_URL);
        data.put("task_id", AiSoftWareCopyRightRedisKey.CALL_BACK + doc.getId());
        String user = "phOperatingManual" + DateUtils.getCurrTime();
        CommonThreadPoolExecutor.addTask(() -> blockingChat(doc.getFileURLs(), q, data, user, api_key));
    }

    // 软著AI助手-PC端说明书
    private void pcOperatingManual(GeneratedDoc doc) {
        String api_key = "app-c0PWYmcythg7bIVxvt4d4kDM";
        String q = "生成电脑端使用说明书";
        Map<String, Object> data = new HashMap<>();
        data.put("ui", doc.getUi());
        data.put("structure", doc.getStructure());
        data.put("demand", doc.getDemand());
        data.put("code", "");
        data.put("baseinfo", JsonUtils.serialize(doc.getBaseinfo()));
        data.put("technical_content", JsonUtils.serialize(doc.getTechnical_content()));
        data.put("callback_url", CALL_BACK_URL);
        data.put("task_id", AiSoftWareCopyRightRedisKey.CALL_BACK + doc.getId());
        String user = "pcOperatingManual" + DateUtils.getCurrTime();
        CommonThreadPoolExecutor.addTask(() -> blockingChat(doc.getFileURLs(), q, data, user, api_key));
    }

    // 软著AI助手-信息采集表
    private void information(GeneratedDoc doc) {
    }

    // ------------
    private String blockingChat(List<String> fileUrls,
                                String question,
                                Map<String, Object> data,
                                String user,
                                String apiKey) {

        DifyConfig difyConfig = DifyConfig.builder()
                .apiKey(apiKey)
                .readTimeout(200 * 1000)
                .baseUrl(DIFY_BASE_URL)
                .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 message = ChatMessage.builder()
                .query(question)
                .user(user)
                .files(files)
                .inputs(data)
                .responseMode(ResponseMode.BLOCKING)
                .build();

        // 发送消息并获取响应
        try {
            ChatMessageResponse chatMessageResponse = chatClient.sendChatMessage(message);
            return chatMessageResponse.getAnswer();
        } catch (IOException | DifyApiException e) {
            logger.error(e.getMessage());
            throw new BusinessException("执行" + user + "生成异常");
        }
    }

    private void streamChat(List<String> fileUrls,
                            String question,
                            Map<String, Object> data,
                            String user,
                            String apiKey) throws IOException, DifyApiException, InterruptedException {
        // 创建聊天客户端
        DifyChatClient chatClient = DifyClientFactory.createChatWorkflowClient(DIFY_BASE_URL, apiKey);

        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();
        // 发送消息并获取响应
        chatClient.sendChatMessageStream(message, new ChatStreamCallback() {
            SSEUtil sseUtil = new SSEUtil(response);

            @Override
            public void onMessage(MessageEvent event) {
                try {
                    if (StringUtils.isNotEmpty(event.getAnswer())) {
                        LargeModelDemandResult largeModelDemandResult = new LargeModelDemandResult();
                        largeModelDemandResult.setCode("0");
                        largeModelDemandResult.setMessage(event.getAnswer());
                        sseUtil.send(JsonUtils.serialize(largeModelDemandResult));
                    }
                } catch (Exception e) {
                    sseUtil.completeByError(e.getMessage());
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void onMessageEnd(MessageEndEvent event) {
                try {
                    sseUtil.send("[DONE]");
                } catch (IOException e) {
                    sseUtil.completeByError(e.getMessage());
                    throw new RuntimeException(e);
                } finally {
                    sseUtil.complete();
                }
                countDownLatch.countDown();
            }
        });
        countDownLatch.await(120, TimeUnit.SECONDS);
    }
}
