import { ApiResult, OpenAIApiParameters, ProxyPatameters } from './declare';
import OpenAIGpt from './openai';
import axios  from 'axios';
const ERROR_RESPONSE: string[] = ['[AUTHORIZATION NEEDED]', '[AUTHORIZATION ERROR]', '[BODY ERROR]','[REQUEST ERROR]']
export default class OpenAIProxy extends OpenAIGpt {
    protected readonly proxySetting: ProxyPatameters;
    constructor(apiKey: string, proxyOption: ProxyPatameters, apiOption: OpenAIApiParameters = {}) {
        super(apiKey, apiOption);
        this.proxySetting = proxyOption;
    }
    /**
     * 重写chatRequest方法
     * @param chatText 
     * @param callChatOption 
     * @param axiosOption 
     */
    override async chatRequest(chatText: string | any[], _paramOption: any, axiosOption?: any): Promise<ApiResult> {
        const opts: any = {
            headers: {
                'Content-Type': 'application/json',
                'authorization': `Bearer ${this.apiKey}`
            },
            method: 'post',
            url: this.proxySetting.serviceurl,
            data: {
                chatText,
                option: _paramOption
            },
            ...axiosOption
        }
        const requestResult = await axios(opts);
        return requestResult.data as ApiResult;
    }
    /**
     * 重写chatRequestInStream方法
     * @param chatText 
     * @param callChatOption 
     * @param attach 
     * @param axiosOption 
     */
    override async chatRequestInStream(chatText:Array<any>, callChatOption: OpenAIApiParameters, attach?: any, axiosOption?: any): Promise<any> {
        // const decoder = new TextDecoder();
        //overContent,
        let  streamText,requestid = Math.ceil(Math.random() * (new Date().getTime() * Math.random()) / 1000);
        const opts:any = {
            headers: {
                'Content-Type': 'application/json',
                'authorization': `Bearer ${this.apiKey}`
            },
            method: 'post',
            url: this.proxySetting.serviceurl +'/stream',
            data: {
                messages:chatText,
                option: callChatOption,
                axiosOption
            },
            responseType: 'stream',
        }
        let unCompleteSegment:string = '';
        axios(opts)
        .then(res => {
            res.data.on('data', (chunk:any) => { 
                streamText = chunk.toString(); //decoder.decode(chunk);
                if (streamText){
                    ///请求的响应发生了错误
                    if (ERROR_RESPONSE.includes(streamText)) {
                        return this.emit('requesterror', { successed: false, requestid, error: 'Request Remote OpenAI Error : ' + streamText });
                    }
                    const fullData = (unCompleteSegment +streamText).split('*&$')
                    unCompleteSegment = '';
                    // console.log('fullData', fullData.length);
                    for (const segment of fullData){
                        if (!segment) continue;
                        try {
                            ////判断接收到的不是一个完整的JSON段了，则该段作为下一次的数据段
                            if (!segment.endsWith('}')) {
                                unCompleteSegment = segment;
                                break;
                            }
                            const objData = Object.assign(JSON.parse(segment), attach);
                            this.emit(objData.finish_reason?'chatdone':'chattext', objData);
                        } catch (errParse) {
                            
                            break;
                            //this.emit('chaterror', { successed: false, requestid, error: 'JSON parse stream message' + errParse });
                        }
                    }
                    
                }
                return;
            });
            //res.data.on('end', () => { this.emit('chatdone', Object.assign(streamText, attach)); });
        }).catch(err=>{
            this.emit('requesterror', { successed: false, requestid, error: 'Axios Error : ' + err });
        })
    }
}