package cn.teammodel.service.impl;

import cn.teammodel.ai.cache.HistoryCache;
import cn.teammodel.ai.deepseek.DeepSeekClient;
import cn.teammodel.common.PK;
import cn.teammodel.model.dto.ai.ChatCompletionReqDto;
import cn.teammodel.model.dto.ai.deepseek.DeepSeekChatRequestDto;
import cn.teammodel.model.dto.ai.deepseek.DeepSeekChatResponse;
import cn.teammodel.model.dto.ai.deepseek.ChatReqDto;
import cn.teammodel.model.entity.ai.ChatSession;
import cn.teammodel.model.entity.ai.DeepSeekSession;
import cn.teammodel.model.entity.ai.DeepSeekSession.DeepSeekMessage;
import cn.teammodel.repository.ChatSessionRepository;
import cn.teammodel.repository.DeepSeekRepository;
import cn.teammodel.security.utils.SecurityUtil;
import cn.teammodel.service.DeepSeekService;
import cn.teammodel.service.DeepSeekSessionService;
import cn.teammodel.utils.RepositoryUtil;
import com.azure.cosmos.models.CosmosPatchOperations;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.BufferedSource;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import com.fasterxml.jackson.databind.ObjectMapper;



/**
 * 描述：访问DeepSeek方法
 */
@Service
@Slf4j
public class DeepSeekServiceImpl implements DeepSeekService {
    @Resource
    private DeepSeekSessionService deepSeekService;

    @Resource
    private DeepSeekRepository deepSeekRepository;
    @Resource
    private ChatSessionRepository chatSessionRepository;

    private final ExecutorService executorService = Executors.newCachedThreadPool();
    private final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 提问
     * @param message
     * @return
     */
    @Override
    public DeepSeekChatResponse ChatAsk(ChatReqDto message) {
        //创建消息列表
        List<ChatReqDto> msg = new ArrayList<>();
        msg.add(message);

        //构建请求头
        DeepSeekChatRequestDto requestBody = new DeepSeekChatRequestDto();
        requestBody.setModel(DeepSeekClient.API_Model);
        requestBody.setMessages(msg);
        requestBody.setTemperature(0);
        requestBody.setMax_tokens(1024);

        //开始时间
        long startTime = System.currentTimeMillis();
        //发起请求
        DeepSeekChatResponse response = DeepSeekClient.SendRequests(requestBody);
        //Map<String, Object> response = DeepSeekClient.SendRequests(requestBody);
        //Map<String, Object> response = SendRequest(requestBody);
        //结束时间
        long endTime = System.currentTimeMillis();
        //思考耗时 秒
        response.setWasteTime((endTime-startTime)/1000);

        if (response.getCode() == 200){
            DeepSeekMessage savaMessage = new DeepSeekMessage();
            savaMessage.setId(response.getId());
            savaMessage.setUserText(message.getContent());
            savaMessage.setAiText(response.getChoices().get(0).getMessage().getContent());
            savaMessage.setRole(response.getChoices().get(0).getMessage().getRole());
            savaMessage.setCreateTime(response.getCreated());
            savaMessage.setFinish_reason(response.getChoices().get(0).getFinish_reason());
            DeepSeekSession session = new DeepSeekSession();
            if (message.getSessionId() != null){
                session = deepSeekRepository.findSessionByIdAndCode(message.getSessionId(), PK.CHAT_SESSION);
                UpdateSession(message, session, savaMessage, response);
            }else {
                UpdateSession(message, session, savaMessage, response);
            }
        }
        return response;
    }


    @Override
    public SseEmitter OKHttpChatSeeEmitterAsk(ChatReqDto message) {
        SseEmitter se = new SseEmitter(-1L);
        //创建消息列表
        List<ChatReqDto> msg = new ArrayList<>();
        msg.add(message);

        //构建请求头
        DeepSeekChatRequestDto requestBody = new DeepSeekChatRequestDto();
        requestBody.setModel(DeepSeekClient.API_Model);
        requestBody.setMessages(msg);
        requestBody.setTemperature(0);
        requestBody.setMax_tokens(1024);
        requestBody.setStream(true);
        if (requestBody.getStream()){
           se =  DeepSeekClient.SendRequestsEmitter(requestBody);

        }else   {

            DeepSeekChatResponse response = DeepSeekClient.SendRequests(requestBody);
        }
        return se;
    }

    /**
     * 提问  流式回答
     * @param chatCompletionReqDto
     * @return
     */
    @Override
    public SseEmitter ChatSeeEmitterAsk(ChatCompletionReqDto chatCompletionReqDto) {
        SseEmitter sseEmitter = new SseEmitter(-1L);
        StringBuilder strContent = new StringBuilder();
        StringBuilder strReasoning = new StringBuilder();
        executorService.execute(()-> {
            try {
                log.info("流式回答开始,问题:{}", chatCompletionReqDto.getText());
                try (CloseableHttpClient client = HttpClients.createDefault()) {
                    HttpPost httpPost = new HttpPost(DeepSeekClient.API_Url);
                    httpPost.setHeader("Content-Type", "application/json");
                    httpPost.setHeader("Accept", "application/json");
                    httpPost.setHeader("Authorization", "Bearer " + DeepSeekClient.API_Key);

                    Map<String, Object> question = new HashMap<>();
                    question.put("role", "user");
                    question.put("content", chatCompletionReqDto.getText());

                    Map<String, Object> requestMap = new HashMap<>();
                    requestMap.put("model", chatCompletionReqDto.getModel());
                    requestMap.put("messages", Collections.singletonList(question));
                    requestMap.put("stream", true);
                    requestMap.put("max_tokens", 1024);

                    String requestBody = objectMapper.writeValueAsString(requestMap);
                    httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
                    try (CloseableHttpResponse response = client.execute(httpPost);
                         BufferedReader reader = new BufferedReader(
                                 new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8))) {
                        String line;
                        while ((line = reader.readLine()) != null) {
                            if (line.startsWith("data: ")) {
                                String jsonData = line.substring(6);
                                if ("[DONE]".equals(jsonData)) {
                                    sseEmitter.send("[DONE]");
                                    // 会话完成，更新历史会话记录
                                    ChatSession.Message message = ChatSession.Message.of(chatCompletionReqDto.getText(), strContent.toString(),chatCompletionReqDto.getModel(),strReasoning.toString());
                                    HistoryCache.updateContext(chatCompletionReqDto.getSessionId(), message);
                                    CosmosPatchOperations options = CosmosPatchOperations.create()
                                            .replace("/updateTime", Instant.now().toEpochMilli())
                                            .add("/history/-", message);
                                    chatSessionRepository.save(chatCompletionReqDto.getSessionId(), PK.of(PK.CHAT_SESSION), ChatSession.class, options);
                                    break;
                                }
                                JsonNode node = objectMapper.readTree(jsonData);
                                String content = node.path("choices")
                                        .path(0)
                                        .path("delta")
                                        .path("content")
                                        .asText("");
                                //推理过程
                                String reasoning_content = node.path("choices")
                                        .path(0)
                                        .path("delta")
                                        .path("reasoning_content")
                                        .asText("");
                                if (!content.isEmpty()) {
                                    strContent.append(content);
                                    sseEmitter.send(content);
                                }
                                if (!reasoning_content.isEmpty()) {
                                    strReasoning.append(reasoning_content);
                                    sseEmitter.send("reasoning:"+ reasoning_content);
                                }
                            }
                        }
                        log.info("流式回答结束,{}",question);
                        sseEmitter.complete();
                    }
                } catch (Exception e) {
                    log.error("处理 Deepseek 请求时发生错误", e);
                    sseEmitter.completeWithError(e);
                }
            } catch (Exception e) {
                log.error("处理 Deepseek 请求时发生错误", e);
                sseEmitter.completeWithError(e);
            }
        });

        return sseEmitter;
    }

    /**
     * 深度思考
     * @param chatCompletionReqDto
     * @return
     */
    @Override
    public SseEmitter ReasonerChatCompletion(ChatCompletionReqDto chatCompletionReqDto) {
        SseEmitter sseEmitter = new SseEmitter(-1L);
        OkHttpClient client = new OkHttpClient.Builder()
                .readTimeout(30, TimeUnit.SECONDS)
                .build();
        MediaType  JSON = MediaType.parse("application/json; charset=utf-8");
        // 构建请求体
//        String requestBody = "{"
//                + "\"model\": \"deepseek-chat\","
//                + "\"messages\": [{\"role\": \"user\", \"content\": \"请介绍一下成都\"}],"
//                + "\"stream\": true,"
//                + "\"temperature\": 0.7"
//                + "}";

        Map<String, Object> question = new HashMap<>();
        question.put("role", "user");
        question.put("content", chatCompletionReqDto.getText());

        Map<String, Object> requestMap = new HashMap<>();
        requestMap.put("model", chatCompletionReqDto.getModel());
        requestMap.put("messages", Collections.singletonList(question));
        requestMap.put("stream", true);
        String requestBody = null;
        try {
            requestBody = objectMapper.writeValueAsString(requestMap);
        } catch (JsonProcessingException e) {
            log.error("处理用户转换问题出错", e);
            sseEmitter.completeWithError(e);
        }

        Request request = new Request.Builder()
                .url(DeepSeekClient.API_Url)
                .post(RequestBody.create(JSON, requestBody))
                .addHeader("Authorization", "Bearer " + DeepSeekClient.API_Key)
                .addHeader("Accept", "text/event-stream")
                .build();
        try(Response response = client.newCall(request).execute()){
            if (response.isSuccessful() && response.body() != null) {

                try (ResponseBody body = response.body()) {
                    if (body != null) {
                        BufferedSource source = body.source();
                        while (!source.exhausted()) {
                            String line = source.readUtf8Line();
                            if (line != null && line.startsWith("data: ")) {
                                String json = line.substring(6).trim();
                                if (json.equals("[DONE]")) {
                                    sseEmitter.send("[DONE]");
                                    break;
                                }
                                JsonNode node = objectMapper.readTree(json);
                                String content = node.path("choices")
                                        .path(0)
                                        .path("delta")
                                        .path("content")
                                        .asText("");
                                String reasoning_content = node.path("choices")
                                        .path(0)
                                        .path("delta")
                                        .path("reasoning_content")
                                        .asText("");
                                if (!content.isEmpty()) {
                                    sseEmitter.send(content);
                                }
                                if (!reasoning_content.isEmpty()) {
                                    sseEmitter.send("reasoning:"+reasoning_content);
                                }
                            }
                        }
                        log.info("流式回答结束,{}",requestBody);
                        sseEmitter.complete();
                    }
                } catch (IOException e) {
                    log.error("处理 Deepseek 请求时发生错误", e);
                    sseEmitter.completeWithError(e);
                }
            }
        }catch (IOException e) {
            log.error("处理 Deepseek 请求时发生错误", e);
            sseEmitter.completeWithError(e);
        }

        return sseEmitter;
    }


    //region 辅助方法
    /**
     * 新增/更新会话
     * @param message
     * @param session
     * @param savaMessage
     * @param response
     */
    private void UpdateSession(ChatReqDto message, DeepSeekSession session, DeepSeekMessage savaMessage, DeepSeekChatResponse response) {
        if (session.getId() == null){
            List<DeepSeekMessage> history = Collections.singletonList(savaMessage);
            String userId = SecurityUtil.getLoginUser().getId();
            session.setId(UUID.randomUUID().toString());
            session.setCode(PK.DEEPSEEK_SESSION);
            session.setTitle("新对话");
            session.setUserId(userId);
            session.setModel(response.getModel());
            session.setCreateTime(Instant.now().toEpochMilli());
            session.setUpdateTime(Instant.now().toEpochMilli());
            session.setHistory(history);
            session = deepSeekRepository.save(session);
        }else {
            session.getHistory().add(savaMessage);
            deepSeekService.updateSession(session, message.getSessionId());
        }
    }
    //endregion

}
