package com.infoepoch.pms.dispatchassistant.controller.langchain.test;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.infoepoch.pms.dispatchassistant.common.component.BaseController;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.util.*;

@RestController
@RequestMapping("/test/chat")
public class ChatController extends BaseController {
    @Autowired
    private ObjectMapper objectMapper;
    private static final CloseableHttpClient httpClient;
    private static final String QW_API_KEY = "sk-7849b6c296b04cbc8df78521c4e0ecb2";
    private static final Logger log = LoggerFactory.getLogger(ChatController.class);
    static {
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(100);
        connManager.setDefaultMaxPerRoute(20);

        httpClient = HttpClients.custom()
                .setConnectionManager(connManager)
                .build();
    }

    @GetMapping(
            value = "/chat-stream",
            produces =  "text/event-stream;charset=UTF-8"
    )
    public SseEmitter chatStream(@RequestParam("message") String message, HttpServletResponse rresponse) throws IOException {
        SseEmitter emitter = new SseEmitter(30 * 60 * 1000L);
        List<Message> messages = new ArrayList<>();
        Message m = new Message();
        m.setRole("user");
        m.setContent(message);
        messages.add(m);
        rresponse.setStatus(HttpServletResponse.SC_OK);
        rresponse.setContentType("text/event-stream;charset=UTF-8");
        rresponse.setCharacterEncoding("UTF-8");
        rresponse.flushBuffer();
        new Thread(() -> {
            try{
                //tool工具构建
                WeatherParameters weatherParameters = new WeatherParameters();
                Map<String,Object> parametersMap = new HashMap<>();
                Map<String,Object> parameters = new HashMap<>();
                parameters.put("type", "string");
                parameters.put("description", "专家的专业领域或关键词，如\"通信\"或\"运维\"");
                Map<String,Object> parameters1 = new HashMap<>();
                parameters1.put("type", "string");
                parameters1.put("description", "可选 专家所在的城市,如\"南京\"或\"苏州\"");
                parametersMap.put("query", parameters);
                parametersMap.put("city", parameters1);
                weatherParameters.setType("object");
                weatherParameters.setProperties(parametersMap);

                QWFuncation qwFuncation = new QWFuncation();
                qwFuncation.setName("search_expert");
                qwFuncation.setDescription("据专业领域和可选地市，查找符合条件的自有人员专家列表");
                qwFuncation.setParameters(weatherParameters);

                QWTool qwTool = new QWTool();
                qwTool.setType("function");
                qwTool.setFunction(qwFuncation);

                List<QWTool> qwTools = new ArrayList<>();
                qwTools.add(qwTool);
                // 请求体构建优化
//                ChatMessageDTO messageDTO = new ChatMessageDTO("qwq-plus",
//                        messages, true);
                ChatMessageToolsDto messageDTO = new ChatMessageToolsDto("qwq-plus",
                        messages, true, qwTools);
                // 使用HttpComponents更优雅的请求构建方式
                String reuqestData = objectMapper.writeValueAsString(messageDTO);
                HttpPost post = new HttpPost("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions");
                post.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + QW_API_KEY);
                post.setEntity(new StringEntity(reuqestData,
                        ContentType.APPLICATION_JSON));

                log.info("发起对话请求:" + reuqestData);
                // 执行请求（带重试）
                try (CloseableHttpResponse response = httpClient.execute(post)) {
                    log.info("请求成功!");
                    processStreamResponse(response, emitter);
                }
            } catch (Exception e) {
                handleException(e, emitter);
            }
        }).start();

        // 超时和完成回调
        emitter.onTimeout(() -> log.warn("SSE连接超时"));
        emitter.onCompletion(() -> log.info("SSE连接完成"));
        return emitter;
    }

    // 流式响应处理私有方法
    private void processStreamResponse(HttpResponse response, SseEmitter emitter) throws IOException {
        StringBuilder toolArgumentsBuffer = new StringBuilder();
        boolean isToolCalling = false;
        String toolName = null;

        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(response.getEntity().getContent()))) {

            String line;
            while ((line = reader.readLine()) != null) {
                if (!line.startsWith("data: ")) continue;

                String jsonStr = line.substring(6).trim();
                if ("[DONE]".equals(jsonStr)) break;

                JsonNode node = objectMapper.readTree(jsonStr);
                JsonNode delta = node.at("/choices/0/delta");

                // 处理工具调用
                if (delta.has("tool_calls")) {
                    isToolCalling = true;
                    JsonNode toolCall = delta.get("tool_calls").get(0);
                    if (toolName == null && toolCall.has("function") && toolCall.get("function").has("name")) {
                        toolName = toolCall.get("function").get("name").asText();
                    }
                    String part = toolCall.get("function").path("arguments").asText("");
                    toolArgumentsBuffer.append(part);
                    continue;
                }

                // 处理普通 content 输出
                String content = delta.path("content").asText(null);
                String reasoning = delta.path("reasoning_content").asText(null);

                if (content == null || content.isEmpty()) {
                    continue;
                }
                log.info(content);
                emitter.send(SseEmitter.event().data(content).id(UUID.randomUUID().toString()));
            }

            if (isToolCalling) {
                String toolArgumentsJson = toolArgumentsBuffer.toString();
                JsonNode args = objectMapper.readTree(toolArgumentsJson);
                String city = args.path("city").asText();
                String query = args.path("query").asText();

                log.info("准备调用工具函数 {}: city={}, query={}", toolName, city, query);
                String result = searchExpert(city, query);
                emitter.send(SseEmitter.event().data(result).id(UUID.randomUUID().toString()));
            }

            emitter.complete();
        }
    }

    private String searchExpert(String city, String query) {
        return "为您推荐如下专家：姓名：张三，城市:" + city + ", 领域:" + query +",荣誉：。。。";
    }

    @PreDestroy
    public void destroy() throws IOException {
        httpClient.close(); // 程序退出时关闭
    }

    // 统一异常处理
    private void handleException(Exception e, SseEmitter emitter) {
        log.error("API调用异常", e);
        if (e instanceof SocketTimeoutException) {
            emitter.completeWithError(new RuntimeException("连接DeepSeek服务超时"));
        } else {
            emitter.completeWithError(new RuntimeException("服务内部错误"));
        }
    }
}