/**
 * 接入AI平台的中间层
 */
import axios from 'axios';
import { request } from "./declare";
import GptBase from "./gptbase"
import { Readable } from 'stream';
// import { ChatReponse } from './declare';
export default class AIMiddlePlatform extends GptBase {

    protected apikey: string;
    protected agent: { endpoint: string, agentid: string };
    /**
     * 
     * @param apikey 调用AI中台 的key
     * @param agent  智能体信息 
     */
    constructor(apikey: string, agent: { endpoint: string, agentid: string }) {
        super();
        this.apikey = apikey;
        this.agent = agent;
    }

    /**
      * 非流式传输聊天请求
      * @param chatText 
      * @param callChatOption 
      * @param axiosOption 
      */
    public async chatRequest(chatText: string | any, callChatOption: any, axiosOption: any = {}): Promise<any> {
        if (!chatText) {
            // this.emit('chaterror', { successed: false, error: 'no text in chat' });
            return { successed: false, error: 'no text in chat' };
        }
        const question = typeof chatText === 'object' ? chatText.text ?? chatText.content : chatText;
        axiosOption = Object.assign({}, axiosOption || { timeout: 60000 })
        const opts: any = {
            headers: {
                'Content-Type': 'application/json',
                'authorization': `Bearer ${this.apikey}`
            },
            method: 'post',
            url: `${this.agent.endpoint}/api/v1/agents/${this.agent.agentid}/completions`,
            data: {
                question,
                session_id: callChatOption.session_id,
                optional: callChatOption.optional,
                stream: false
            },
            ...axiosOption
        }
        const response = await request(opts);
        if (!response.successed || response.data.code) return { successed: false, error: 'failed' };
        const {answer:message,session_id} = response.data.data;
        // this.emit('chatdone', { successed: true, segment: message, text: message, finish_reason: 'stop', index: 0, session_id })
        return { successed: true, message:[{message:{content:message}}],session_id };
    }
    /**
     * 流式传输聊天请求
     * @param chatText 
     * @param callChatOption 
     * @param attach 
     * @param axiosOption 
     * @returns 
     */
    override async chatRequestInStream(chatText: string | any, callChatOption: any, attach?: any, axiosOption?: any): Promise<any> {
        if (!chatText) this.emit('chaterror', { successed: false, error: 'no text in chat' });
        // console.log('Question===>', chatText)
        const question = typeof chatText === 'object' ? chatText.text??chatText.content : chatText;
        axiosOption = Object.assign({}, axiosOption || { timeout: 60000 })
        let requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000);
        try {
            const opts: any = {
                headers: {
                    'Content-Type': 'application/json',
                    'authorization': `Bearer ${this.apikey}`
                },
                method: 'post',
                url: `${this.agent.endpoint}/api/v1/agents/${this.agent.agentid}/completions`,
                data: {
                    question,
                    session_id: callChatOption.session_id,
                    stream: true,
                    optional: callChatOption.optional,
                },
                responseType: 'stream',
                ...axiosOption
            }
            const response = await axios(opts);
            const readableStream = Readable.from(response.data);
            let index = 0, session_id,fullanswer='',errorKeeped=[],chunks:any=[];
            for await (const chunk of readableStream) {
                ///可能接收到的数据不完整，导致JSON.parse失败
                let answerData = null, jsonStr = '';
                try{
                    jsonStr = chunk.toString().split('data:')
                    if (jsonStr.length) jsonStr = jsonStr[jsonStr.length-1]+''
                    answerData = JSON.parse(errorKeeped.join('') + jsonStr);
                }catch(e){
                    ////如果发生了JSON解析错误，则当前的数据不完整，留着拼凑下一回数据
                    // console.log('json parse error===>', errorKeeped.join('') + jsonStr)
                    errorKeeped.push(jsonStr)
                    // console.log('After Push===>', errorKeeped.join('') )
                    continue;
                }
                errorKeeped = [];
                const { answer, running_status, reference } = answerData.data;
                if (running_status === true) continue;
                const segment = answer ? answer.replace(fullanswer,''):''
                fullanswer = answer ?? fullanswer;
                if (!session_id) session_id = answerData.data.session_id;
                if (reference && reference.chunks && reference.chunks.length) chunks = chunks.concat(reference.chunks)
                const finished = answerData.data === true;
                let output = { successed: true, requestid, segment: segment, chunks, text: fullanswer, finish_reason: finished ? 'stop' : null, index: index++, session_id };
                if (attach) output = Object.assign({}, output, attach);
                this.emit(finished ? 'chatdone' : 'chattext', output)
            }
            return { successed: true, requestid }
        } catch (error) {
            
            // this.emit('requesterror', { successed: false, requestid, error: 'call axios faied ' + error });
            // return { successed: false, requestid }
        }
    }
}