package com.ch.jedge.jbot.intent.param;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ch.jedge.jbot.JedgeLlmUtil;
import com.ch.jedge.jbot.knbase.JedgeGptApp;
import com.changhong.jedge.JESocketClient;
import com.changhong.jedge.JMgbusService;
import com.changhong.qlib.QData;
import com.changhong.qlib.util.NumberUtils;

import java.util.*;

import static com.ch.jedge.jbot.JEJBotLLMConst.ival_max_timeout_count;

/**
 *  大模型的中文语义参数提取器
 *      结构：
 *      （1） 参数表， 参数取值表
 *      （2） 输入文字
 *      （3） 备选参数
 *      （4） 输出格式
 *      （5） 附加说明
 *
 *
 */
public class JedgeDataSetter {

    private static class JedgeDataSet {
        public final int dsId;
        private final boolean isNullable;
        private final String srcMod;
        private final String cbUri;
        protected final JSONArray words = new JSONArray();
        int ttl = 0;

        public JedgeDataSet(JSONArray words) {
            updateWords(words);
            this.dsId = NumberUtils.randomInt(0x7FFFFFF);
            this.isNullable = true;
            this.srcMod = "";
            this.cbUri = "";
        }

        public JedgeDataSet(String srcMod, String cbUri, JSONArray words, boolean nullable) {
            updateWords(words);
            this.dsId = NumberUtils.randomInt(0x7FFFFFF);
            this.isNullable = nullable;
            this.srcMod = srcMod;
            this.cbUri = cbUri;
        }

        //mediaSearch:查询媒体咨询相关功能,根据用户提供的信息提取关键字,并查找对应的影片信息;
        //mediaPlay:播放媒体,根据已经命中的媒体信息,去播放队对应的影片或歌曲,并设置对应的播放参数;
        //mediaSave:记录用户的个性化喜好,根据已经播放的历史或内容,记住用户的一些播放参数;
        public String getDatasetValueDef() {
            StringBuilder re = new StringBuilder();
            synchronized (words) {
                for (Object w : this.words) {
                    String disc = ((JSONObject) w).getString("disc");
                    String valDisc = (disc!=null)?
                            String.format("\"%s\"(%s);",((JSONObject)w).getString("key"), disc):
                            String.format("\"%s\";",((JSONObject)w).getString("key"));
                    re.append(valDisc);
                }
            }
            return re.toString();
        }

        public String getValueKeyList() {
            StringBuilder re = new StringBuilder();
            synchronized (this.words) {
                for (Object w : words) {
                    String key = ((JSONObject) w).getString("key");
                    if (re.length() > 0) re.append(',');
                    re.append(key);
                }
            }
            return re.toString();
        }

        public void updateWords(JSONArray words) {
            this.ttl = 0;
            synchronized (this.words) {
                this.words.clear();
                for (Object w : words) {
                    if (w instanceof String) {
                        w = QData.fromString((String) w).asJsonObject();
                        this.words.add(w);
                    } else if (w instanceof JSONObject)
                        this.words.add(w);
                }
            }
        }

    }

    private final JMgbusService service;
    protected final String targetMessageFormat;
    private final Map<String, JedgeDataSet> dataSetCache = new HashMap<>();
    protected final JedgeLLMParamPicker dsPicker = new JedgeLLMParamPicker();

    public JedgeDataSetter(JMgbusService service, String paramFormat) {
        this.service = service;
        this.targetMessageFormat = paramFormat;
    }

    //获取词库
    public String getDatasetValueDefine(String pmKey) {
        synchronized (dataSetCache) {
            JedgeDataSet ds = dataSetCache.get(pmKey);
            if(ds!=null) {
                String dsStr = ds.getDatasetValueDef();
                if(ds.isNullable) { dsStr += ",若无法取值,则字段为空;";}
                return dsStr;
            }
        }
        return "";
    }

    public String getDatasetValList(String dsKey) {
        //"媒体指令"的取值列表：mediaSearch,mediaPlay,mediaSave;
        synchronized (dataSetCache) {
            JedgeDataSet ds = dataSetCache.get(dsKey);
            if(ds!=null) {
                String dsStr = String.format("\"%s\"的取值范围:%s",dsKey, ds.getValueKeyList());
                if(ds.isNullable) { dsStr += ",若无法取值,则字段为空;";}
                return dsStr;
            }
        }
        return "";
    }

    public int updateDataset2Cache(int dsid, String dsKey, JSONArray words) {
        if(JedgeGptApp.isDebugMode())
            JESocketClient.LogSt("数据集更新(%s):%s",dsKey, words);
        synchronized (dataSetCache) {
            JedgeDataSet old = dataSetCache.get(dsKey);
            if(old==null) {
                old =  new JedgeDataSet(words);
                dataSetCache.put(dsKey, old);
                return old.dsId;
            } else {
                old.updateWords(words);
            }
        }
        return dsid;
    }

    public int addDataSet(int dsid, String srcMod, String cbUri, String dsKey,
                          JSONArray words, boolean nullable) {
        //添加数据集
//        if(JedgeGptApp.isDebugMode()) {
//            JESocketClient.LogSt("创建数据集(%s):%s", dsKey, words);
//        }
        synchronized (dataSetCache) {
            JedgeDataSet old = dataSetCache.get(dsKey);
            if(old==null) {
                old =  new JedgeDataSet(srcMod, cbUri, words, nullable);
                dataSetCache.put(dsKey, old);
                return old.dsId;
            } else {
                old.updateWords(words);
            }
        }
        return dsid;
    }


    public void onHeartbeat() {
        synchronized (dataSetCache) {
            List<String> toDel = new ArrayList<>();
            for(String key : dataSetCache.keySet()) {
                JedgeDataSet dsCache = dataSetCache.get(key);
                if(dsCache!=null) {
                    if(dsCache.ttl>-1) dsCache.ttl ++;
                    if(dsCache.ttl > ival_max_timeout_count ) {
                        //超时退出
                        toDel.add(key);
                    }
                }
            }
            for(String dmKey :toDel) {
                dataSetCache.remove(dmKey);
            }
        }
    }

}
