package cn.iocoder.yudao.module.llm.service.http;


import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.module.llm.framework.backend.config.LLMBackendProperties;
import cn.iocoder.yudao.module.llm.service.http.vo.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import kong.unirest.UnirestException;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 训练相关接口
 */
@Service
@Slf4j
public class TrainHttpService {

    @Resource
    private LLMBackendProperties llmBackendProperties;

    /**
     * 训练集列表 GET
     */
    public String datasetList(Map<String, String> headers){
        String datasetList = llmBackendProperties.getDatasetList();
        String res = HttpUtils.get(datasetList, headers);
        return res;
    }

    /**
     * 上传训练集 POST
     */
    public String datasetCreate(Map<String, String> headers, String body){
        String datasetCreate = llmBackendProperties.getDatasetCreate();
        String res = HttpUtils.post(datasetCreate, headers, body);
        return res;
    }

    /**
     * 删除训练集 DELETE
     */
    public String datasetDelete(Map<String,String> headers){
        String datasetDelete = llmBackendProperties.getDatasetDelete();
        String res = HttpUtils.del(datasetDelete, headers);
        return res;
    }

    /**
     * 训练集标注 GET
     */
    public String annotationTaskList(Map<String, String> headers){
        String annotationTaskList = llmBackendProperties.getAnnotationTaskList();
        String res = HttpUtils.get(annotationTaskList, headers);
        return res;
    }

    /**
     * 标注信息 GET
     */
    public String annotationTask(Map<String, String> headers){
        String annotationTask = llmBackendProperties.getAnnotationTask();
        String res = HttpUtils.get(annotationTask, headers);
        return res;
    }


    /**
     * 保存标注 POST
     */
    public String annotationTaskSave(Map<String, String> headers, String body){
        String annotationTaskSave = llmBackendProperties.getAnnotationTaskSave();
        String res = HttpUtils.post(annotationTaskSave, headers, body);
        return res;
    }

    /**
     * 大模型列表 GET
     */
    public String modelsList(String modelName){
        Map<String, String> headers = new HashMap<>();
        login(headers);
        String modelsList = llmBackendProperties.getModelsList();
        String res = HttpUtils.get(modelsList + "?modelName=" + modelName, headers);
        return res;
    }

    /**
     * 基础模型列表 GET
     */
    public String baseModelList(Map<String, String> headers){
        String baseModelList = llmBackendProperties.getBaseModelList();
        String res = HttpUtils.get(baseModelList, headers);
        return res;
    }

    /**
     * 登录 POST
     */
    public AigcLoginRespVO login(Map<String, String> headers){
        headers.put("Content-Type", "application/json");
        headers.put("Pragma", "no-cache");
        String login = llmBackendProperties.getLogin();
        AigcLoginReqVO req = new AigcLoginReqVO(llmBackendProperties.getLoginUsername(), llmBackendProperties.getLoginPassword());
        String res = HttpUtils.post(login, headers,  JSON.toJSONString(req));
        log.info("登录接口返回：{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        if (aigcRespVO.isSuccess() && aigcRespVO.getData() != null){
            AigcLoginRespVO aigcLoginRespVO = JSON.parseObject(aigcRespVO.getData().toString(), AigcLoginRespVO.class);
            headers.put("X-Token", aigcLoginRespVO.getToken());
            AigcAccountRespVO aigcAccountRespVO = account(headers);
            if (aigcAccountRespVO != null && CollUtil.isNotEmpty(aigcAccountRespVO.getTenants())) {
                aigcLoginRespVO.setTenantId(aigcAccountRespVO.getTenants().get(0).getId());
                headers.put("X-Tenant-Id", aigcLoginRespVO.getTenantId());
                log.info(" login:{}", aigcAccountRespVO);
                return aigcLoginRespVO;
            }
        }
        return null;
    }

    public AigcAccountRespVO account(Map<String, String> headers){
        String account = llmBackendProperties.getAccount();
        String res = HttpUtils.get(account, headers);
        log.info(" account:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        if (aigcRespVO.isSuccess() && aigcRespVO.getData() != null){
            AigcAccountRespVO aigcAccountRespVO = JSON.parseObject(aigcRespVO.getData().toString(), AigcAccountRespVO.class);
            log.info(" account:{}", aigcAccountRespVO);
            return aigcAccountRespVO;
        }
        return null;
    }

    /**
     * 创建微调任务 POST
     */
    public AigcFineTuningCreateRespVO finetuningCreate(Map<String, String> headers, AigcFineTuningCreateReqVO req){
        login(headers);
        // TODO: 在上个方法中已经将数据集的文件id赋予，调试时需要写死再放开
//        String fileId = "6237ed4d-a046-479c-80d6-8579a0283994";
//        req.setFileId(fileId);
        String res = HttpUtils.post(llmBackendProperties.getFinetuningCreate(), headers, JSON.toJSONString(req));
        log.info(" finetuningCreate:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        var aigcFineTuningCreateRespVO = JSON.parseObject(res, AigcFineTuningCreateRespVO.class);
        log.info(" finetuningCreate:{}", aigcFineTuningCreateRespVO);
        return aigcFineTuningCreateRespVO;
    }
    /**
     * 根据表名称查询数据
     */
    public String modelTableQuery(Map<String, String> headers, String tableName,String query){
        String url = String.format(llmBackendProperties.getTableDataQuery(),tableName);
        url = url+query;
        String res = HttpUtils.get(url, headers);
        log.info(" model query info :{}", res);
        return res;

    }

    public AigcFineTuningDetailRespVO finetuningDetail(Map<String, String> headers, String jobId){
        login(headers);
        String finetuningDetail = llmBackendProperties.getFinetuningDetail();
        String res = HttpUtils.get(finetuningDetail + "/" + jobId, headers);
        log.info(" finetuningDetail:{}", res);
        try {
            AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
            if (aigcRespVO.isSuccess() && aigcRespVO.getData() != null){
                AigcFineTuningDetailRespVO aigcFineTuningDetailRespVO = JSON.parseObject(aigcRespVO.getData().toString(), AigcFineTuningDetailRespVO.class);
                log.info(" finetuningDetail:{}", aigcFineTuningDetailRespVO);
                return aigcFineTuningDetailRespVO;
            }
        }catch (Exception e){
            log.error(" finetuningDetail:{}", e.getMessage());
        }

        return null;
    }

    public AigcRespVO finetuningDelete(Map<String, String> headers, String jobId) {
        login(headers);
        String finetuningDetail = llmBackendProperties.getFinetuningDetail();
        String res = HttpUtils.del(finetuningDetail + "/" + jobId, headers);
        log.info(" finetuningDelete:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        log.info(" finetuningDelete:{}", aigcRespVO);
        return aigcRespVO;
    }

    public String finetuningFileList(Map<String, String> headers) {
        String finetuningFileList = llmBackendProperties.getFinetuningFileList();
        String res = HttpUtils.get(finetuningFileList, headers);
        log.info(" finetuningFileList:{}", res);
        return res;
    }


    public String autoEvaluation(String prompt,String dataSetPrompt) {
        Map<String,String> map = new HashMap<>();
        map.put("accept","application/json");
        map.put("Content-Type","application/json");
        String autoEvaluation = llmBackendProperties.getAutoEvaluation();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("prompt",prompt);
        jsonObject.put("dataSetPrompt",dataSetPrompt);
        List<String> dimension = Stream.of("事实性错误","情感倾向性","语义连贯性").collect(Collectors.toList());
        jsonObject.put("dimension",dimension);
        String body = JSONObject.toJSONString(jsonObject);
        String res = HttpUtils.post(autoEvaluation, map, body);
        log.info(" autoEvaluation:{}", res);
        JSONObject resJson = JSONObject.parseObject(res);
        JSONObject response = resJson.getJSONObject("response");
        String content = response.getString("content");
        return content;

    }

    /**
     * 模型对话 POST
     */
    public String modelCompletions(Map<String, String> headers, String body){
        String finetuningCreate = llmBackendProperties.getModelCompletions();
        String res = HttpUtils.post(finetuningCreate, headers, body);
        return res;
    }

    public AigcRespVO modelDeploy(Map<String, String> headers,AigcModelDeploySaveReq req){
        login(headers);
        String modelDeploy = llmBackendProperties.getModelDeploy();
        String res = HttpUtils.post(modelDeploy, headers, JSON.toJSONString(req));
        log.info(" modelDeploy:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        return aigcRespVO;
    }
    public AigcRespVO modelUndeploy(Map<String, String> headers, String baseModelName) {
        login(headers);
        String modelDeploy = llmBackendProperties.getModelUndeploy();
        String res = HttpUtils.post(modelDeploy + baseModelName, headers,"");
        log.info(" modelDeploy:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        log.info(" modelDeploy:{}", aigcRespVO);
        return aigcRespVO;
    }

    /**
     * 模型服务创建
     */
    public AigcModelCreateRespVO modelCreate(Map<String, String> headers, AIgcModelCreateSaveReq req) {
        login(headers);
        String modelDeploy = llmBackendProperties.getModelCreate();
        String res = HttpUtils.post(modelDeploy, headers, JSON.toJSONString(req));
        log.info(" modelDeploy:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        if (aigcRespVO.isSuccess() && aigcRespVO.getData() != null){
            AigcModelCreateRespVO aigcModelCreateRespVO = JSON.parseObject(aigcRespVO.getData().toString(), AigcModelCreateRespVO.class);
            log.info(" modelDeploy:{}", aigcModelCreateRespVO);
            return aigcModelCreateRespVO;
        }
        log.info(" modelDeploy:{}", aigcRespVO);
        return null;
    }

    /**
     * AIGC文件上传
     * @param headers
     * @param inputStream
     * @param fileName
     * @return
     * @throws UnirestException
     * @throws IOException
     */
    public AigcDatasetFileRespV0 AigcUploadFile(Map<String, String> headers, InputStream inputStream, String fileName) throws UnirestException, IOException {
        String aigcFileUpload = llmBackendProperties.getAigcFileUpload();
        login(headers);
        headers.remove("Content-Type");
        try  {
            // 上传文件
            HttpResponse<String> uploadResponse = Unirest.post(aigcFileUpload)
                    .headers(headers)
                    .field("file", inputStream, fileName)
                    .field("purpose", "fine-tune")
                    .asString();
            log.info("Response Body: " + uploadResponse.getBody());
            AigcRespVO aigcRespVO = JSON.parseObject(uploadResponse.getBody(), AigcRespVO.class);
            if (aigcRespVO.isSuccess()){
                AigcDatasetFileRespV0 aigcDatasetFileRespV0 = JSON.parseObject(aigcRespVO.getData().toString(), AigcDatasetFileRespV0.class);
                log.info("模型工厂上传文件 aigcDatasetFileRespV0:{}", aigcDatasetFileRespV0);
                return aigcDatasetFileRespV0;
            }
            return null;
        }catch (Exception e){
            return null;
        }
    }


    public AigcRespVO finetuningCancle(Map<String, String> headers, String jobId) {
        login(headers);
        String finetuningCancel = llmBackendProperties.getFinetuningCancel();
        String url = String.format(finetuningCancel,jobId);
        String res = HttpUtils.del(url, headers);
        log.info(" finetuningDelete:{}", res);
        AigcRespVO aigcRespVO = JSON.parseObject(res, AigcRespVO.class);
        log.info(" finetuningDelete:{}", aigcRespVO);
        return aigcRespVO;

    }

    public String getTrainLog(String params) {
        String finetuningLog = llmBackendProperties.getFinetuningLog();
        return HttpUtils.get(finetuningLog+params, null);
    }

    public String getCheckFileList(String name){
        String checkFileList = llmBackendProperties.getCheckFileList();
        return HttpUtils.get(checkFileList + name, null);
    }

    public String getCheckFile(String name,String path){
        String checkFileList = llmBackendProperties.getCheckFileList();
        return checkFileList + name + "&&file_path=" + path;

    }
}
