package com.goafanti.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.goafanti.ChatAI.BaiduChatErrorEnums;
import com.goafanti.ChatAI.bo.*;
import com.goafanti.common.error.BusinessException;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Configuration
public class BaiduChatUtils {
    private final static  Integer MAX_IP_COUNT=5;

    @Value(value = "${baidu.ApiKey}")
    private   String baiduApiKey=null;

    @Value(value = "${baidu.SecretKey}")
    private   String baiduSecretKey=null;
    @Autowired
    private RedisUtil redisUtil;

    /*文心一言地址*/
    private static final String BAIDU_CHAT_WXYY_URL="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=";
    /*Ernie-Lite地址*/
    private static final String BAIDU_CHAT_ERNIE_LITE_URL="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=";
    /*ERNIE_BOT_4*/
    private static final String ERNIE_BOT_4="https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro?access_token=";
    /*accessToken获取地址*/
    private static final String BAIDU_ACCESSTOKEN_URL="https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&";


    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().connectTimeout(120000, TimeUnit.MILLISECONDS)
            .readTimeout(120000, TimeUnit.MILLISECONDS)
            .build();

    @Async
    public void sendBaiduAiStream(InputSendChat inputSendChat) throws IOException {
        LoggerUtils.debug(getClass(),"ERNIE Bot");
        sendStream(inputSendChat,BAIDU_CHAT_WXYY_URL);
    }

    @Async
    public void sendERNIEBOT4Stream(InputSendChat inputSendChat) throws IOException {
        LoggerUtils.debug(getClass(),"ERNIE_BOT_4");
        sendStream(inputSendChat,ERNIE_BOT_4);
    }

    @Async
    public void sendStream(InputSendChat inputSendChat,String httpUrl) throws IOException {
        SseResult res =  SseMap.sseEmitterMap.get(inputSendChat.getUserId());
//        if (checkIp()){
//            res.sseEmitter.send(new OutChatER(4004,"访问超过最大限制，陌生游客每天最多访问5次"));
//            res.sseEmitter.complete();
//            SseMap.sseEmitterMap.remove(inputSendChat.getUserId());
//            return;
//        }
        BufferedReader reader=null;
        InputStreamReader inputStreamReader=null;
        OutputStream outputStream=null;
        try {

            String baidu_url=httpUrl+getRedisBaiduAccessToken();
            URL url = new URL(baidu_url);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoInput(true);
            connection.setDoOutput(true);
            // 构造请求体
//            String requestBody = "{\"messages\":[{\"role\":\"user\",\"content\":\"给我介绍一条从四川自驾到拉萨的路线\"}],\"stream\":true}";
            String requestBody=JSON.toJSONString(inputSendChat);
//            System.out.println(requestBody);
            byte[] postData = requestBody.getBytes(StandardCharsets.UTF_8);
            connection.setRequestProperty("Content-Length", String.valueOf(postData.length));
            outputStream =connection.getOutputStream();
            outputStream.write(postData);
            InputStream responseStream = connection.getInputStream();
            inputStreamReader = new InputStreamReader(responseStream, "UTF-8");
            reader = new BufferedReader(inputStreamReader);
            String line;

            while ((line = reader.readLine())!= null) {
                // 每行数据中以 "data:" 开头的部分即为实际的响应数据
//                        System.out.println(line);
                if (StringUtils.isNotBlank(line)){
                    if (line.startsWith("data:")) {
                        String data = line.substring("data:".length()).trim();
                        JSONObject jsonObject = JSONObject.parseObject(data);
                        String result=jsonObject.getString("result");
                        if (StringUtils.isNotBlank(result)){
                            Boolean isEnd = jsonObject.getBoolean("is_end");
                            res.sseEmitter.send(data);
                            if(isEnd){
                                break;
                            }
                        }
                        //错误返回格式{"error_code":110,"error_msg":"Access token invalid or no longer valid"}
                    }else if(line.startsWith("{")) {
                        JSONObject jsonObject = JSONObject.parseObject(line);
                        Integer errorCode = jsonObject.getInteger("error_code");
                        OutChatER out=new OutChatER();
                        if (errorCode!=null){
                            out.setError_code(errorCode);
                            if (errorCode.equals("336003")){
                                out.setError_msg(BaiduChatErrorEnums.BycodeGetMsg(errorCode)+jsonObject.getString("error_msg"));
                            }else {
                                out.setError_msg(BaiduChatErrorEnums.BycodeGetMsg(errorCode));
                            }
                        }
                        String errorStr=JSON.toJSONString(out);
                        LoggerUtils.debug(getClass(),errorStr);
                        res.sseEmitter.send(errorStr);
                    }
                }
            }
            res.sseEmitter.complete();
        } catch (MalformedURLException e) {
            e.printStackTrace();
            sendJitaoBaiWen(inputSendChat.getUserId(),"data:{\"error_code\":\"2\",\"error_msg\":\"域名解析异常\"}");
        } catch (ProtocolException e) {
            e.printStackTrace();
        }catch (IllegalStateException e){
            LoggerUtils.debug(this.getClass(),"前端网页已关闭");
        } finally {
            inputStreamReader.close();
            outputStream.close();
            reader.close();
            res.sseEmitter.complete();
            SseMap.sseEmitterMap.remove(inputSendChat.getUserId());
        }

    }




    public  String  getBaiduAccessToken() throws IOException {
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "");
        StringBuffer url= new StringBuffer(BAIDU_ACCESSTOKEN_URL)
                .append("client_id=").append(baiduApiKey).append("&client_secret=").append(baiduSecretKey);
        Request request = new Request.Builder()
                .url(url.toString())
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        String result=response.body().string();
        HashMap<String,Object> map = JSON.parseObject(result, HashMap.class);
        String  accessToken = map.get("access_token").toString();
        LoggerUtils.debug(getClass(),"获取accessToken="+accessToken);
        return accessToken;
    }





    private void sendJitaoBaiWen(String userId, String s) throws IOException {
        SseResult res =  SseMap.sseEmitterMap.get(userId);
        res.sseEmitter.send(s);
    }


    private String  getRedisBaiduAccessToken() {
        String redisAccessToken;
        String redisTime=redisUtil.getString("baiduAccessTime");
        if (redisTime !=null){
            Calendar cal = Calendar.getInstance();
            Long redisAccessTime=Long.valueOf(redisTime);
            if (cal.getTimeInMillis()>redisAccessTime){
                redisUtil.deleteString("baiduAccessToken");
                redisUtil.deleteString("baiduAccessTime");
                redisAccessToken=pushRedisBaiduAccessToken();
                LoggerUtils.debug(getClass(),"accessToken过期，重新获取！");
            }else {
                redisAccessToken=  redisUtil.getString("baiduAccessToken");
            }
        }else {
            redisAccessToken=pushRedisBaiduAccessToken();
            LoggerUtils.debug(getClass(),"accessToken不存在,从百度获取！");
        }
        return redisAccessToken;
    }

    private String pushRedisBaiduAccessToken() {
        String baiduAccessToken;
        try {
            baiduAccessToken = getBaiduAccessToken();
        } catch (IOException e) {
            throw new BusinessException("baiduAccessToken获取失败");
        }
        //获取当前系统时间
        Calendar cal = Calendar.getInstance();
        //将时间增加三十天
        cal.add(Calendar.DATE, 30);
        //获取改变后的时间
        Long baiduAccessTime= cal.getTimeInMillis();
        redisUtil.deleteString("baiduAccessToken");
        redisUtil.deleteString("baiduAccessTime");
        redisUtil.setString("baiduAccessToken",baiduAccessToken);
        redisUtil.setString("baiduAccessTime",baiduAccessTime.toString());
        return baiduAccessToken;
    }


    public boolean checkIp() {
        String hostIp = IpUtils.getHostIp();
        String ipCount = redisUtil.getString(hostIp);
        Integer count;
        if (ipCount==null){
            count=1;
            redisUtil.setString(hostIp,count.toString());
        }else {
            count=Integer.parseInt(ipCount);
            if (count>=MAX_IP_COUNT){
                return true;
            }else {
                count++;
                redisUtil.setString(hostIp,count.toString());
//                System.out.println(count);
            }
        }
        return false;
    }

}
