package com.storlead.knowledge.api;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.storlead.framework.common.result.Result;
import com.storlead.knowledge.config.DifyProperties;
import com.storlead.knowledge.entity.AiMessageEntity;
import com.storlead.knowledge.pojo.dto.ChatDTO;
import com.storlead.knowledge.pojo.dto.QueryPageDTO;
import com.storlead.knowledge.service.AiMessageService;
import com.storlead.knowledge.utils.HttpService;
import com.storlead.knowledge.utils.JacksonHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;


@RestController
@RequestMapping("/chat/")
@Api(tags = "知识库: 对话及流程")
public class ChatController {

    private static final Logger log = LoggerFactory.getLogger(ChatController.class);

    @Resource
    private HttpService httpService;

    @Resource
    private DifyProperties difyProperties;

    @Resource
    private AiMessageService aiMessageService;

    /**
     * 创建聊天 blocking模式
     * @param chatDTO
     * @return
     * @throws JsonProcessingException
     */
    @PostMapping("chat")
    @ApiOperation("创建聊天")
    public Result<Object> chat(@RequestBody ChatDTO chatDTO) throws JsonProcessingException {
        String url = difyProperties.getBaseUrl() + "chat-messages";
        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(chatDTO);
        Result<Object> result = httpService.post(url, null, "Bearer "+chatDTO.getAppId(), body, new TypeReference<>() {});

        // 异步保存聊天记录（不影响主流程）
        if (result.isSuccess() && result.getResult() != null) {
            try {
                saveBlockingMessage(chatDTO, result.getResult());
            } catch (Exception e) {
                log.error("保存聊天记录失败", e);
            }
        }

        return result;
    }


    /**
     * 创建聊天 流式模式
     * @param chatDTO
     * @return
     * @throws IOException
     */
    @PostMapping(value = "chatStreaming", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @ApiOperation("创建聊天 流式返回")
    public SseEmitter chatStreaming(@RequestBody ChatDTO chatDTO) throws IOException {

        SseEmitter emitter = new SseEmitter(0L); // 0 = 不超时

        String url = difyProperties.getBaseUrl() + "chat-messages";

        String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(chatDTO);
        httpService.postStream(
                url,
                "Bearer " +chatDTO.getAppId(),
                body,
                emitter,
                (lastData) -> {
                    try {
                        saveStreamingMessage(chatDTO, lastData);
                    } catch (Exception e) {
                        log.error("保存流式聊天记录失败", e);
                    }
                }
        );

        return emitter;
    }

    @GetMapping("messages")
    @ApiOperation("获取聊天记录（支持关键字搜索和分页）")
    public Result<Object> listMessages(QueryPageDTO page) {
        return Result.ok(aiMessageService.pageQuery(page));
    }

    @GetMapping("history")
    @ApiOperation("获取应用的对话历史")
    public Result<Object> list(ChatDTO chatDTO) {
        String url = difyProperties.getBaseUrl()  + "conversations";
        return httpService.get(
                url,
                Map.of("user", chatDTO.getUser()),
                "Bearer "+difyProperties.getAppKeys().get(chatDTO.getAppId()),
                new TypeReference<>() {}
        );
    }

    /**
     * 保存 blocking 模式的聊天记录
     */
    private void saveBlockingMessage(ChatDTO chatDTO, Object responseData) {
        try {
            String json = JacksonHolder.OBJECT_MAPPER.writeValueAsString(responseData);
            JsonNode root = JacksonHolder.OBJECT_MAPPER.readTree(json);
            System.out.println(root);
            AiMessageEntity entity = new AiMessageEntity();
            entity.setTaskId(getJsonText(root, "task_id"));
            entity.setMessageId(getJsonText(root, "message_id"));
            entity.setConversationId(getJsonText(root, "conversation_id"));
            entity.setAppId(chatDTO.getAppId());
            entity.setInputs(chatDTO.getInputs() != null ? JacksonHolder.OBJECT_MAPPER.writeValueAsString(chatDTO.getInputs()) : null);
            entity.setQuery(chatDTO.getQuery());
            entity.setResponseMode(chatDTO.getResponse_mode());
            entity.setUserId(chatDTO.getUser());
            entity.setAnswer(getJsonText(root, "answer"));
            entity.setCreatedAt(Integer.parseInt(getJsonText(root, "created_at")));

            aiMessageService.save(entity);
        } catch (Exception e) {
            log.error("解析并保存blocking聊天记录失败", e);
        }
    }

    /**
     * 保存 streaming 模式的聊天记录（从 message_end 事件中解析）
     */
    private void saveStreamingMessage(ChatDTO chatDTO, String lastData) {
        try {
            // lastData 格式: {"event":"message_end","task_id":"...","message_id":"...","conversation_id":"...","metadata":{...}}
            JsonNode root = JacksonHolder.OBJECT_MAPPER.readTree(lastData);

            AiMessageEntity entity = new AiMessageEntity();
            entity.setTaskId(getJsonText(root, "task_id"));
            entity.setMessageId(getJsonText(root, "message_id"));
            entity.setConversationId(getJsonText(root, "conversation_id"));
            entity.setAppId(chatDTO.getAppId());
            entity.setInputs(chatDTO.getInputs() != null ? JacksonHolder.OBJECT_MAPPER.writeValueAsString(chatDTO.getInputs()) : null);
            entity.setQuery(chatDTO.getQuery());
            entity.setResponseMode(chatDTO.getResponse_mode());
            entity.setUserId(chatDTO.getUser());
            // streaming 模式下 answer 在 metadata 中逐句返回，message_end 事件本身不含完整 answer，此处留空
            entity.setAnswer(getJsonText(root, "answer"));
            entity.setCreatedAt(Integer.parseInt(getJsonText(root, "created_at")));

            aiMessageService.save(entity);
        } catch (Exception e) {
            log.error("解析并保存streaming聊天记录失败", e);
        }
    }

    /**
     * 安全获取 JSON 节点文本值
     */
    private String getJsonText(JsonNode node, String field) {
        JsonNode value = node.get(field);
        return value != null && !value.isNull() ? value.asText() : null;
    }

}

