package com.sonic.cow.client.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.sonic.cow.client.ResponseChatClient;
import com.sonic.cow.client.request.*;
import com.sonic.cow.client.response.ResponseChatResponse;
import com.sonic.cow.domain.bo.ChatOutputTextBo;
import com.sonic.cow.utils.JsonExtractor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class ResponseChatClientImpl implements ResponseChatClient {

    @Value("${volcengine.apiKey}")
    private String apiKey;
    @Value("${volcengine.contextCachingModel}")
    private String contextCachingModel;
    @Value("${volcengine.responseUrl:https://ark.ap-southeast.bytepluses.com/api/v3/responses}")
    private String responseUrl;

    @Override
    public ResponseChatResponse responseStructuredChat(String responseId, String instructions, List<InputRequest> inputRequests, List<Tools> tools, String functionParam, Float temperature, Float topp) {
        ResponseChatResponse response = responseChatV2(responseId, instructions, inputRequests, tools, null, true, functionParam, temperature, topp);
        if(response == null) {
            return null;
        }
        //处理格式化输出
        ChatOutputTextBo bo = JsonExtractor.extractMessageAndScore(response.getMessage());
        if(bo != null) {
            response.setMessage(bo.getMessage());
            response.setScore(bo.getScore());
        }
        return response;
    }

    @Override
    public ResponseChatResponse responseStructuredChat(String responseId, String instructions, List<InputRequest> inputRequests, List<Tools> tools, boolean caching) {
        ResponseChatResponse response = responseChat(responseId, instructions, inputRequests, tools, null, caching);
        if(response == null) {
            return null;
        }
        //处理格式化输出
        ChatOutputTextBo bo = JsonExtractor.extractMessageAndScore(response.getMessage());
        if(bo != null) {
            response.setMessage(bo.getMessage());
            response.setScore(bo.getScore());
        }
        return response;
    }


    @Override
    public ResponseChatResponse responseChat(String responseId, String instructions, List<InputRequest> inputRequests, List<Tools> tools, Text text, boolean caching) {
        try {
            ResponseChatCompletionRequest request = ResponseChatCompletionRequest.builder()
                    .model(contextCachingModel)
                    .previousResponseId(responseId)
                    .instructions(instructions)
                    .input(inputRequests)
                    .text(text)
                    .thinking(Thinking.builder().type("disabled").build())
                    .caching(Caching.builder().type(caching ? "enabled" : "disabled").build())
                    .store(true)
                    .tools(StringUtils.isEmpty(responseId) ? tools : null)
                    .build();
            ObjectMapper mapper = new ObjectMapper();
            String requestBody = mapper.writeValueAsString(request);
            log.info("===> responseChat requestBody : {}", requestBody);
            HttpResponse<String> response = Unirest.post(responseUrl)
                    .header("Authorization", "Bearer " + apiKey)
                    .header("Content-Type", "application/json")
                    .body(requestBody)
                    .asString();
            String body = response.getBody();
            log.info("===> responseChat responseBody : {}",  body);
            //解析出id、内容
            JSONObject jsonObject = JSONObject.parseObject(body);
            JSONObject error = jsonObject.getJSONObject("error");
            if(error != null && StringUtils.isNotEmpty(error.getString("code"))) {
                //返回空，并删除缓存
                return ResponseChatResponse.builder()
                        .code(error.getString("code"))
                        .build();
            }
            String respId = jsonObject.getString("id");
            JSONObject outputJSONObject = jsonObject.getJSONArray("output").getJSONObject(0);
            JSONObject contentJSONObject = outputJSONObject.getJSONArray("content") == null ? null : outputJSONObject.getJSONArray("content").getJSONObject(0);
            String content = contentJSONObject == null ? null : contentJSONObject.getString("text");
            String type = outputJSONObject.getString("type");
            String name = outputJSONObject.getString("name");
            String arguments = outputJSONObject.getString("arguments");
            String callId = outputJSONObject.getString("call_id");
            //构造出参对象
            return ResponseChatResponse.builder()
                    .responseId(respId)
                    .message(content)
                    .type(type)
                    .functionCallName(name)
                    .functionCallArguments(arguments)
                    .functionCallId(callId)
                    .build();
        } catch (Exception e) {
            log.error("===> responseChat error : ", e);
        }
        return null;
    }

    @Override
    public ResponseChatResponse responseChatV2(String responseId, String instructions, List<InputRequest> inputRequests, List<Tools> tools, Text text, boolean caching, String functionParam, Float temperature, Float topp) {
        try {
            ResponseChatCompletionRequest request = ResponseChatCompletionRequest.builder()
                    .model(contextCachingModel)
                    .previousResponseId(responseId)
                    .instructions(instructions)
                    .input(inputRequests)
                    .text(text)
                    .thinking(Thinking.builder().type("disabled").build())
                    .caching(Caching.builder().type(caching ? "enabled" : "disabled").build())
                    .store(true)
                    .tools(StringUtils.isEmpty(responseId) ? tools : null)
                    .temperature(temperature == null ? 1.0f : temperature)
                    .topP(topp == null ? 0.7f : topp)
                    .build();
            ObjectMapper mapper = new ObjectMapper();
            String requestBody = mapper.writeValueAsString(request);
            log.info("===> responseChatV2 requestBody : {}", requestBody);
            HttpResponse<String> response = Unirest.post(responseUrl)
                    .header("Authorization", "Bearer " + apiKey)
                    .header("Content-Type", "application/json")
                    .body(requestBody)
                    .asString();
            String body = response.getBody();
            log.info("===> responseChatV2 responseBody : {}",  body);
            //解析出id、内容
            JSONObject jsonObject = JSONObject.parseObject(body);
            JSONObject error = jsonObject.getJSONObject("error");
            if(error != null && StringUtils.isNotEmpty(error.getString("code"))) {
                //返回空，并删除缓存
                return ResponseChatResponse.builder()
                        .code(error.getString("code"))
                        .build();
            }
            String respId = jsonObject.getString("id");
            JSONArray outputList = jsonObject.getJSONArray("output");
            for (int i = 0; i < outputList.size(); i++) {
                JSONObject outputJSONObject = outputList.getJSONObject(i);
                JSONObject contentJSONObject = outputJSONObject.getJSONArray("content") == null ? null : outputJSONObject.getJSONArray("content").getJSONObject(0);
                String content = contentJSONObject == null ? null : contentJSONObject.getString("text");
                String type = outputJSONObject.getString("type");
                String name = outputJSONObject.getString("name");
                String arguments = outputJSONObject.getString("arguments");
                String callId = outputJSONObject.getString("call_id");
                //判断文本内容是否有值，如果有值的话那么直接快速返回
                if(StringUtils.isNotEmpty(content)) {
                    //判断内容中是否有函数调用的方法名称，为了兼容返回混乱json结果的问题
                    if(content.indexOf("get_ai_image") > 0) {
                        return ResponseChatResponse.builder()
                                .responseId(respId)
                                .message(content)
                                .type("function_call")
                                .functionCallName("get_ai_image")
                                .functionCallArguments(functionParam)
                                .functionCallId(callId)
                                .build();
                    }
                    ChatOutputTextBo bo = JsonExtractor.extractMessageAndScore(content);
                    if(StringUtils.isNotEmpty(bo.getMessage()) && !bo.getMessage().equals(content)) {
                        //构造出参对象，直接快速返回掉
                        return ResponseChatResponse.builder()
                                .responseId(respId)
                                .message(content)
                                .type(type)
                                .functionCallName(name)
                                .functionCallArguments(arguments)
                                .functionCallId(callId)
                                .build();
                    }
                    //当出现多条数据，第一条为文本，第二条为function call，那么文本值为空的时候跳出本次循环，执行下一条数据的逻辑
                    //并且还有下一条数据的时候才跳出循环
                    if(StringUtils.isEmpty(bo.getMessage()) && i < outputList.size()) {
                        continue;
                    }
                }
                //构造出参对象
                return ResponseChatResponse.builder()
                        .responseId(respId)
                        .message(content)
                        .type(type)
                        .functionCallName(name)
                        .functionCallArguments(arguments)
                        .functionCallId(callId)
                        .build();
            }
        } catch (Exception e) {
            log.error("===> responseChatV2 error : ", e);
        }
        return null;
    }

}
