package com.ruoyi.platform.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.platform.annotations.CheckDuplicate;
import com.ruoyi.platform.domain.*;
import com.ruoyi.platform.domain.dependencydomain.ProjectDepency;
import com.ruoyi.platform.domain.dependencydomain.TrainTaskDepency;
import com.ruoyi.platform.mapper.ExperimentDao;
import com.ruoyi.platform.mapper.ModelDependency1Dao;
import com.ruoyi.platform.service.*;
import com.ruoyi.platform.utils.HttpUtils;
import com.ruoyi.platform.utils.JacksonUtil;
import com.ruoyi.platform.utils.JsonUtils;
import com.ruoyi.platform.utils.YamlUtils;
import com.ruoyi.platform.vo.ModelsVo;
import com.ruoyi.platform.vo.NewDatasetVo;
import com.ruoyi.system.api.constant.Constant;
import com.ruoyi.system.api.model.LoginUser;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * (Experiment)表服务实现类
 *
 * @author makejava
 * @since 2023-10-18 13:37:48
 */
@Service("experimentService")
public class ExperimentServiceImpl implements ExperimentService {
    @Resource
    private ExperimentDao experimentDao;
    @Resource
    private ModelsService modelsService;
    @Resource
    private DatasetService datasetService;
    @Resource
    private ModelDependencyService modelDependencyService;
    @Resource
    private DatasetTempStorageService datasetTempStorageService;
    @Resource
    @Lazy
    private WorkflowService workflowService;

    @Resource
    @Lazy
    private ExperimentInsService experimentInsService;

    @Resource
    private ResourceOccupyService resourceOccupyService;

    @Resource
    private ModelDependency1Dao modelDependency1Dao;

    @Value("${argo.url}")
    private String argoUrl;
    @Value("${argo.convert}")
    private String argoConvert;
    @Value("${argo.workflowRun}")
    private String argoWorkflowRun;
    @Value("${git.localPath}")
    String localPath;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Experiment queryById(Integer id) throws IOException {
        List<ExperimentIns> experimentInsList = this.experimentInsService.getByExperimentId(id);
        Experiment experiment = this.experimentDao.queryById(id);
        if (experiment == null) {
            return null;
        }
        experiment.setExperimentInsList(experimentInsList);
        return experiment;
    }

    /**
     * 分页查询
     *
     * @param experiment  筛选条件
     * @param pageRequest 分页对象
     * @return 查询结果
     */
    @Override
    public Page<Experiment> queryByPage(Experiment experiment, PageRequest pageRequest) {
        List<Experiment> experimentList = this.experimentDao.queryAllByLimit(experiment, pageRequest);
        long total = this.experimentDao.count(experiment);
        // 存储所有实验的ID列表，查询实验对应的流水线
        for (Experiment exp : experimentList) {
            Long workflowId = exp.getWorkflowId();
            Workflow correspondingWorkflow = this.workflowService.queryById(workflowId);
            String workflowName = correspondingWorkflow.getName();
            exp.setWorkflowName(workflowName);
        }

        return new PageImpl<>(experimentList, pageRequest, total);
    }


    /**
     * 分页查询实验状态
     *
     * @param experiment  筛选条件
     * @param pageRequest 分页对象
     * @return 查询结果
     */
    public Page<Experiment> selectStatus(Experiment experiment, PageRequest pageRequest) throws IOException {
        List<Experiment> experimentList = this.experimentDao.queryAllByLimit(experiment, pageRequest);
        // 存储所有实验的ID列表
        List<Integer> experimentIds = new ArrayList<>();
        //对于每一个从Experiment表中查询出来的id，可能有多个实例，每个实例的实验id是不同的
        for (Experiment exp : experimentList) {
            //返回所有实验ID相同的实例列表
            List<ExperimentIns> experimentInsList = this.experimentInsService.getByExperimentId(exp.getId());
            exp.setExperimentInsList(experimentInsList);
        }
        return new PageImpl<>(experimentList);
    }

    /**
     * 新增数据
     *
     * @param experiment 实例对象
     * @return 实例对象
     */
    @Override
    public Experiment insert(Experiment experiment) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        checkDeclaredName(experiment);
        experiment.setCreateBy(loginUser.getUsername());
        experiment.setUpdateBy(loginUser.getUsername());
        experiment.setState(Constant.State_valid);
        this.experimentDao.insert(experiment);
        return experiment;
    }

    /**
     * 修改数据
     *
     * @param experiment 实例对象
     * @return 实例对象
     */
    @Override
    public Experiment update(Experiment experiment) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        checkDeclaredName(experiment);
        experiment.setUpdateBy(loginUser.getUsername());
        this.experimentDao.update(experiment);
        return this.queryById(experiment.getId());
    }


    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.experimentDao.deleteById(id) > 0;
    }

    @Override
    @Transactional
    public String removeById(Integer id) throws Exception {
        Experiment experiment = experimentDao.queryById(id);
        if (experiment == null) {
            throw new Exception("实验不存在");
        }

        //判断权限，只有admin和创建者本身可以删除该实验
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        String createdBy = experiment.getCreateBy();
        if (!(StringUtils.equals(username, "admin") || StringUtils.equals(username, createdBy))) {
            throw new Exception("无权限删除该实验");
        }

        List<ExperimentIns> experimentInsList = experimentInsService.queryByExperimentId(experiment.getId());
        if (experimentInsList != null && experimentInsList.size() > 0) {
            throw new Exception("该实验存在实例，无法删除");
        }
        resourceOccupyService.deleteTaskState(Constant.TaskType_Workflow, Long.valueOf(id), null);
        experiment.setState(Constant.State_invalid);
        return this.experimentDao.update(experiment) > 0 ? "删除成功" : "删除失败";


    }

    /**
     * 运行已经创建的实验
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public Experiment runExperiment(Integer id) throws Exception {
        //先查出实验记录
        Experiment experiment = this.queryById(id);
        if (experiment == null) {
            System.out.println("No experiment");
        }
        Workflow workflow = workflowService.queryById(experiment.getWorkflowId());
        if (workflow == null) {
            throw new RuntimeException("流水线不存在，请先创建流水线");
        }

        String dag = workflow.getDag();
        // 调argo转换接口
        try {
            String convertRes = HttpUtils.sendPost(argoUrl + argoConvert, dag);
            if (convertRes == null || StringUtils.isEmpty(convertRes)) {
                throw new Exception("转换流水线失败");
            }
            Map<String, Object> converMap = JsonUtils.jsonToMap(convertRes);
            if (converMap.get("data") == null) {
                throw new RuntimeException("转换流水线失败");
            }

            // 判断积分和资源是否足够
            Map<String, Map<String, Object>> resourceInfo = (Map<String, Map<String, Object>>) converMap.get("resource_info");
            if (resourceInfo == null) {
                throw new Exception("未配置运行所需资源");
            }
            for (Map.Entry<String, Map<String, Object>> entry : resourceInfo.entrySet()) {
                Map<String, Object> node = entry.getValue();
                resourceOccupyService.haveResource((Integer) node.get("computing_resource_id"), 1);
            }

            // 组装运行接口json
            Map<String, Object> runReqMap = new HashMap<>();
            runReqMap.put("data", converMap.get("data"));
            //这里全局参数是一个json数组，需要转换成一个list<Map>
            List<Map<String, Object>> params = JacksonUtil.parseJSONStr2MapList(StringUtils.isEmpty(experiment.getGlobalParam()) ? "[]" : experiment.getGlobalParam());
            runReqMap.put("params", params);
            // 实验字段的Map，不要写成一行！否则会返回null
            Map<String, Object> experimentMap = new HashMap<>();
            experimentMap.put("name", "experiment-" + experiment.getId());
            runReqMap.put("experiment", experimentMap);

            Map<String, Object> output = (Map<String, Object>) converMap.get("output");
            // 调argo运行接口
            String runRes = HttpUtils.sendPost(argoUrl + argoWorkflowRun, JsonUtils.mapToJson(runReqMap));

            if (runRes == null || StringUtils.isEmpty(runRes)) {
                throw new RuntimeException("运行流水线失败");
            }
            Map<String, Object> runResMap = JsonUtils.jsonToMap(runRes);
            Map<String, Object> data = (Map<String, Object>) runResMap.get("data");
            //判断data为空
            if (data == null || MapUtils.isEmpty(data)) {
                throw new RuntimeException("运行流水线失败");
            }


            Map<String, Object> metadata = (Map<String, Object>) data.get("metadata");
            // 插入记录到实验实例表
            ExperimentIns experimentIns = new ExperimentIns();
            //获取训练参数

            experimentIns.setExperimentId(experiment.getId());
            experimentIns.setArgoInsNs((String) metadata.get("namespace"));
            experimentIns.setArgoInsName((String) metadata.get("name"));
            experimentIns.setStatus(Constant.Pending);

            //传入实验全局参数
            experimentIns.setGlobalParam(experiment.getGlobalParam());
            //替换argoInsName
            String outputString = JsonUtils.mapToJson(output);
            experimentIns.setNodesResult(outputString.replace("{{workflow.name}}", (String) metadata.get("name")));


            //得到dependendcy
            Map<String, Object> converMap2 = JsonUtils.jsonToMap(JacksonUtil.replaceInAarry(convertRes, params));
            Map<String, Object> dependendcy = (Map<String, Object>) converMap2.get("model_dependency");
            Map<String, Object> trainInfo = (Map<String, Object>) converMap2.get("component_info");

            Map<String, Object> metricRecord = (Map<String, Object>) runResMap.get("metric_record");
            if (metricRecord != null) {
                //把训练用的数据集也放进去
                addDatesetToMetric(metricRecord, trainInfo);
                experimentIns.setMetricRecord(JacksonUtil.toJSONString(metricRecord));
            }
            //插入ExperimentIns表中
            ExperimentIns insert = experimentInsService.insert(experimentIns);
            //插入到模型依赖关系表
            if (dependendcy != null && trainInfo != null) {
                insertModelDependencyNew(dependendcy, trainInfo, output, insert.getMetricRecord(), insert.getId(), workflow.getId(), experiment.getId(), experiment.getName(), experiment.getGlobalParam());
            }

            Map<String, Object> datasetDependendcy = (Map<String, Object>) converMap2.get("dataset_dependency");
            //暂存数据集元数据{}
            if (datasetDependendcy != null && trainInfo != null) {
                insertDatasetTempStorage(datasetDependendcy, trainInfo, experiment.getId(), insert.getId(), experiment.getName(), experiment.getWorkflowId());
            }

            // 记录开始扣积分
            for (Map.Entry<String, Map<String, Object>> entry : resourceInfo.entrySet()) {
                Map<String, Object> node = entry.getValue();
                resourceOccupyService.startDeduce((Integer) node.get("computing_resource_id"), 1, Constant.TaskType_Workflow, Long.valueOf(id), Long.valueOf(insert.getId()), experiment.getWorkflowId(), experiment.getName(), entry.getKey(), Constant.State_building);
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        List<ExperimentIns> updatedExperimentInsList = experimentInsService.getByExperimentId(id);
        experiment.setExperimentInsList(updatedExperimentInsList);
        experimentInsService.updateExperimentStatus(id);
        return experiment;
    }

    private void addDatesetToMetric(Map<String, Object> metricRecord, Map<String, Object> trainInfo) {
        processMetricPart(metricRecord, trainInfo, "train", "model_train");
        processMetricPart(metricRecord, trainInfo, "evaluate", "model_evaluate");
    }

    private void processMetricPart(Map<String, Object> metricRecord, Map<String, Object> trainInfo, String metricKey, String trainInfoKey) {
        List<Map<String, Object>> metricList = (List<Map<String, Object>>) metricRecord.get(metricKey);
        if (metricList != null) {
            for (Map<String, Object> metricRecordItem : metricList) {
                String taskId = (String) metricRecordItem.get("task_id");
                Map<String, Object> trainInfoPart = (Map<String, Object>) trainInfo.get(trainInfoKey);
                if (trainInfoPart != null) {
                    Map<String, Object> trainInfoDetails = (Map<String, Object>) trainInfoPart.get(taskId);
                    if (trainInfoDetails != null) {
                        List<Map<String, Object>> datasets = (List<Map<String, Object>>) trainInfoDetails.get("datasets");
                        if (datasets != null) {
                            //查询名字再回填
//                            for (int i = 0; i < datasets.size(); i++) {
//                                Dataset dataset = datasetService.queryById(Integer.valueOf((String) datasets.get(i).get("dataset_id")));
//                                datasets.get(i).put("dataset_name", dataset.getName());
//                            }
                            metricRecordItem.put("datasets", datasets);
                        }
                    }
                }
            }
        }
    }


    private void insertModelDependency(Map<String, Object> dependendcy, Map<String, Object> trainInfo, Integer experimentInsId, String experimentName) throws Exception {
        Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator();
        Map<String, Object> modelTrain = (Map<String, Object>) trainInfo.get("model_train");
        Map<String, Object> modelEvaluate = (Map<String, Object>) trainInfo.get("model_evaluate");
        Map<String, Object> modelExport = (Map<String, Object>) trainInfo.get("model_export");
        while (dependendcyIterator.hasNext()) {
            ModelDependency modelDependency = new ModelDependency();
            Map.Entry<String, Object> entry = dependendcyIterator.next();
            Map<String, Object> modelDel = (Map<String, Object>) entry.getValue();
            Map<String, Object> source = (Map<String, Object>) modelDel.get("source");
            List<Map<String, Object>> test = (List<Map<String, Object>>) modelDel.get("test");
            List<Map<String, Object>> target = (List<Map<String, Object>>) modelDel.get("target");
            String sourceTaskId = (String) source.get("task_id");

            Map<String, Object> modelTrainMap = (Map<String, Object>) modelTrain.get(sourceTaskId);
            //处理project数据
            Map<String, String> projectMap = (Map<String, String>) modelTrainMap.get("project");
            ProjectDepency projectDepency = new ProjectDepency();
            projectDepency.setBranch(projectMap.get("branch"));
            String projectUrl = projectMap.get("url");
            projectDepency.setUrl(projectUrl);
            projectDepency.setName(projectUrl.substring(projectUrl.lastIndexOf('/') + 1, projectUrl.length() - 4));
            //依赖项目
            modelDependency.setProjectDependency(JsonUtils.objectToJson(projectDepency));
            //处理镜像
            Map<String, String> imagesMap = (Map<String, String>) modelTrainMap.get("image");
            modelDependency.setTrainImage(imagesMap.get("name"));
            List<Map<String, Object>> trainParamList = (List<Map<String, Object>>) modelTrainMap.get("params");
            modelDependency.setTrainParams(JsonUtils.objectToJson(trainParamList));
            //处理source数据
            List<Map<String, Object>> modelsList = (List<Map<String, Object>>) modelTrainMap.get("models");
            if (modelsList != null) {
                for (int i = 0; i < modelsList.size(); i++) {
                    Map<String, Object> model = modelsList.get(i);
                    Models models = modelsService.queryById((Integer) model.get("model_id"));
                    if (models == null) {
                        throw new Exception("源模型不存在");
                    }
                    model.put("model_name", models.getName());
                }
                //父模型
                modelDependency.setParentModels(JsonUtils.objectToJson(modelsList));
            }
            List<Map<String, Object>> datasetsList = (List<Map<String, Object>>) modelTrainMap.get("datasets");
            if (datasetsList != null) {
                for (int i = 0; i < datasetsList.size(); i++) {
                    Map<String, Object> datasets = datasetsList.get(i);
                    Dataset dataset = datasetService.queryById((Integer) datasets.get("dataset_id"));
                    if (dataset == null) {
                        throw new Exception("源数据集不存在");
                    }
                    datasets.put("dataset_name", dataset.getName());
                }
            }
            //训练数据集
            modelDependency.setTrainDataset(JsonUtils.objectToJson(datasetsList));
            TrainTaskDepency trainTaskDepency = new TrainTaskDepency();
//            trainTaskDepency.setTaskId(sourceTaskId);
            trainTaskDepency.setInsId(experimentInsId);
            trainTaskDepency.setName(experimentName);
            //训练任务
            modelDependency.setTrainTask(JsonUtils.objectToJson(trainTaskDepency));
            modelDependency.setExpInsId(experimentInsId);
            List<Map<String, Object>> resultTestDatasets = new ArrayList<Map<String, Object>>();
            //处理test数据
            if (test != null) {
                for (int i = 0; i < test.size(); i++) {
                    Map<String, Object> testMap = test.get(i);
                    String testTaskId = (String) testMap.get("task_id");
                    Map<String, Object> evaluateMap = (Map<String, Object>) modelEvaluate.get(testTaskId);
                    List<Map<String, Object>> realDataSetList = (List<Map<String, Object>>) evaluateMap.get("datasets");
                    for (int j = 0; j < realDataSetList.size(); j++) {
                        Map<String, Object> realDataSet = realDataSetList.get(j);
                        Dataset dataset = datasetService.queryById((Integer) realDataSet.get("dataset_id"));
                        if (dataset == null) {
                            throw new Exception("源数据集不存在");
                        }
                        realDataSet.put("dataset_name", dataset.getName());
                        resultTestDatasets.add(realDataSet);
                    }
                }

                //测试数据集
                modelDependency.setTestDataset(JsonUtils.objectToJson(resultTestDatasets));
            }
            //处理target数据
            if (target != null) {
                for (int i = 0; i < target.size(); i++) {
                    Map<String, Object> targetMap = target.get(i);
                    String targetaskId = (String) targetMap.get("task_id");
                    Map<String, Object> exportMap = (Map<String, Object>) modelExport.get(targetaskId);
                    List<Map<String, Object>> modelTargetList = (List<Map<String, Object>>) exportMap.get("models");
                    modelDependency.setState(2);
                    for (int j = 0; j < modelTargetList.size(); j++) {
                        Map<String, Object> model = modelTargetList.get(i);
                        modelDependency.setVersion((String) model.get("model_version"));
                        modelDependency.setCurrentModelId((Integer) model.get("model_id"));
                        //因为可能有多成果模型，多次插入
                        modelDependencyService.insert(modelDependency);
                    }
                }
            } else {
                modelDependency.setState(2);
                modelDependencyService.insert(modelDependency);
            }

        }
    }

    /**
     * 存储数据集元数据到临时表
     */
    private void insertDatasetTempStorage(Map<String, Object> datasetDependendcy, Map<String, Object> trainInfo, Integer experimentId, Integer experimentInsId, String experimentName, Long workflowId) {
        Iterator<Map.Entry<String, Object>> dependendcyIterator = datasetDependendcy.entrySet().iterator();
        Map<String, Object> datasetExport = (Map<String, Object>) trainInfo.get("dataset_export");
        Map<String, Object> datasetPreprocess = (Map<String, Object>) trainInfo.get("general-data-process");
        while (dependendcyIterator.hasNext()) {
            Map.Entry<String, Object> entry = dependendcyIterator.next();
            Map<String, Object> modelDel = (Map<String, Object>) entry.getValue();
            Map<String, Object> source = (Map<String, Object>) modelDel.get("source"); //被处理数据集
//            List<Map<String, Object>> test = (List<Map<String, Object>>) modelDel.get("test");
            List<Map<String, Object>> target = (List<Map<String, Object>>) modelDel.get("target"); //导出的数据集

            String sourceTaskId = (String) source.get("task_id");
            Map<String, Object> datasetPreprocessMap = (Map<String, Object>) datasetPreprocess.get(sourceTaskId);
            //处理project数据
            // 拼接需要的参数
            Map<String, Object> projectMap = (Map<String, Object>) datasetPreprocessMap.get("project");
            String projectUrl = (String) projectMap.get("url");
            String projectName = projectUrl.substring(projectUrl.lastIndexOf('/') + 1, projectUrl.length() - 4);
            projectMap.put("name", projectName);
            Map<String, Object> sourceParams = new HashMap<>();
            sourceParams.put("name", experimentName);
            sourceParams.put("ins_id", experimentInsId);
            sourceParams.put("experiment_id", experimentId);
            sourceParams.put("train_name", sourceTaskId);
            sourceParams.put("preprocess_code", projectMap);
            sourceParams.put("workflow_id", workflowId);

            ArrayList<Map<String, Object>> sourceDatasets = (ArrayList<Map<String, Object>>) datasetPreprocessMap.get("datasets");
            if (sourceDatasets != null && sourceDatasets.size() > 0) {
                Map<String, Object> dataset = sourceDatasets.get(0);
                sourceParams.put("repo_id", dataset.get("dataset_id"));
                sourceParams.put("identifier", dataset.get("dataset_identifier"));
                sourceParams.put("version", dataset.get("dataset_version"));
                sourceParams.put("owner", dataset.get("owner"));
            }

            if (target != null && target.size() > 0) {
                for (Map<String, Object> targetMap : target) {
                    String targetTaskId = (String) targetMap.get("task_id");
                    Map<String, Object> datasetExportMap = (Map<String, Object>) datasetExport.get(targetTaskId);
                    List<Map> datasets = (List<Map>) datasetExportMap.get("datasets");
                    if (datasets != null) {
                        for (Map<String, Object> dataset : datasets) {
                            DatasetTempStorage datasetTempStorage = new DatasetTempStorage();
                            datasetTempStorage.setRepoId(Integer.valueOf((String) dataset.get("dataset_id")));
                            datasetTempStorage.setName((String) dataset.get("dataset_identifier"));
                            datasetTempStorage.setVersion((String) dataset.get("dataset_version"));
                            datasetTempStorage.setCreateBy((String) dataset.get("owner"));
                            datasetTempStorage.setSource(JacksonUtil.toJSONString(sourceParams));
                            datasetTempStorage.setState(Constant.State_valid);
                            datasetTempStorageService.insert(datasetTempStorage);
                        }
                    }

                }
            }
        }
    }

    private void insertModelDependencyNew(Map<String, Object> dependendcy, Map<String, Object> trainInfo, Map<String, Object> output, String metricRecord, Integer experimentInsId, Long workflowId, Integer experimentId, String experimentName, String globalParam) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String gitLinkUsername = loginUser.getSysUser().getUserName();
        Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator();
        Map<String, Object> modelTrain = (Map<String, Object>) trainInfo.get("model_train");
        Map<String, Object> modelEvaluate = (Map<String, Object>) trainInfo.get("model_evaluate");
        Map<String, Object> modelExport = (Map<String, Object>) trainInfo.get("model_export");
        Map<String, Object> param_output = (Map<String, Object>) output.get("param_output");

        while (dependendcyIterator.hasNext()) {
            ModelsVo modelMetaVo = new ModelsVo();
            modelMetaVo.setInsId(experimentInsId);
            modelMetaVo.setOwner(gitLinkUsername);
            ModelDependency1 modelDependency = new ModelDependency1();
            modelDependency.setOwner(gitLinkUsername);
            modelDependency.setState(Constant.State_building);

            Map.Entry<String, Object> entry = dependendcyIterator.next();
            Map<String, Object> modelDel = (Map<String, Object>) entry.getValue();
            Map<String, Object> source = (Map<String, Object>) modelDel.get("source");
            List<Map<String, Object>> test = (List<Map<String, Object>>) modelDel.get("test");
            List<Map<String, Object>> target = (List<Map<String, Object>>) modelDel.get("target");

            String sourceTaskId = (String) source.get("task_id");
            Map<String, Object> modelTrainMap = (Map<String, Object>) modelTrain.get(sourceTaskId);

            //处理project数据
            Map<String, String> projectMap = (Map<String, String>) modelTrainMap.get("project");
            ProjectDepency projectDepency = new ProjectDepency();
            projectDepency.setBranch(projectMap.get("branch"));
            String projectUrl = projectMap.get("url");
            projectDepency.setUrl(projectUrl);
            projectDepency.setName(projectUrl.substring(projectUrl.lastIndexOf('/') + 1, projectUrl.length() - 4));
            modelMetaVo.setProjectDepency(projectDepency);

            //处理镜像
            Map<String, String> imagesMap = (Map<String, String>) modelTrainMap.get("image");
            modelMetaVo.setImage(imagesMap.get("name"));

            //处理训练参数
            HashMap<String, Object> trainParam = new HashMap<>();
            JSONArray jsonArray = JSONArray.parseArray(globalParam);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                String paramName = jsonObject.getString("param_name");
                String paramValue = jsonObject.getString("param_value");
                if (YamlUtils.isNumeric(paramValue)) {
                    BigDecimal bigDecimal = new BigDecimal(paramValue);
                    trainParam.put(paramName, bigDecimal);
                } else {
                    trainParam.put(paramName, paramValue);
                }
            }
            modelMetaVo.setParams(trainParam);

            //处理指标
            HashMap<String, Object> metricMap = JSON.parseObject(metricRecord, HashMap.class);
            modelMetaVo.setMetricsParams(metricMap);

            //训练数据集
            List<Map<String, Object>> trainDatasetList = (List<Map<String, Object>>) modelTrainMap.get("datasets");
            if (trainDatasetList != null) {
                List<NewDatasetVo> trainDatasets = new ArrayList<>();
                for (Map<String, Object> dataset : trainDatasetList) {
                    if (!dataset.containsKey("dataset_ref")) {
                        NewDatasetVo newDatasetVo = new NewDatasetVo();
                        newDatasetVo.setId(Integer.valueOf((String) dataset.get("dataset_id")));
                        newDatasetVo.setName((String) dataset.get("dataset_name"));
                        newDatasetVo.setVersion((String) dataset.get("dataset_version"));
                        newDatasetVo.setIdentifier((String) dataset.get("dataset_identifier"));
                        newDatasetVo.setOwner((String) dataset.get("owner"));
                        trainDatasets.add(newDatasetVo);
                    }
                }
                modelMetaVo.setTrainDatasets(trainDatasets);
            }

            //训练任务
            TrainTaskDepency trainTask = new TrainTaskDepency();
            trainTask.setWorkflowId(workflowId);
            trainTask.setInsId(experimentInsId);
            trainTask.setName(experimentName);
            trainTask.setExperimentId(experimentId);
            trainTask.setTaskId(sourceTaskId);
            modelMetaVo.setTrainTask(trainTask);

            //处理source数据
            List<Map<String, Object>> modelsList = (List<Map<String, Object>>) modelTrainMap.get("models");
            if (modelsList != null) {
                Map<String, Object> parentModelMap = modelsList.get(0);
                String id = (String) parentModelMap.get("model_id");
                String identifier = (String) parentModelMap.get("model_identifier");
                String version = (String) parentModelMap.get("model_version");

                HashMap<String, Object> map = new HashMap<>();
                map.put("repoId", id);
                map.put("identifier", identifier);
                map.put("version", version);
                String parentModel = JSON.toJSONString(map);
                modelMetaVo.setParentModel(parentModel);

                modelDependency.setParentModel(parentModel);
                modelDependency.setMeta(JSON.toJSONString(modelMetaVo));
                modelDependency1Dao.insert(modelDependency);
            }

            //处理test数据
            if (test != null) {
                for (Map<String, Object> testMap : test) {
                    String testTaskId = (String) testMap.get("task_id");
                    Map<String, Object> evaluateMap = (Map<String, Object>) modelEvaluate.get(testTaskId);
                    List<Map<String, Object>> testDatasetList = (List<Map<String, Object>>) evaluateMap.get("datasets");
                    List<NewDatasetVo> testDatasets = new ArrayList<>();
                    for (Map<String, Object> dataset : testDatasetList) {
                        if (!dataset.containsKey("dataset_ref")) {
                            NewDatasetVo newDatasetVo = new NewDatasetVo();
                            newDatasetVo.setId(Integer.valueOf((String) dataset.get("dataset_id")));
                            newDatasetVo.setName((String) dataset.get("dataset_name"));
                            newDatasetVo.setVersion((String) dataset.get("dataset_version"));
                            newDatasetVo.setIdentifier((String) dataset.get("dataset_identifier"));
                            newDatasetVo.setOwner((String) dataset.get("owner"));
                            testDatasets.add(newDatasetVo);
                        }
                    }
                    modelMetaVo.setTestDatasets(testDatasets);
                }
            }

            //处理target数据
            if (target != null) {
                for (int i = 0; i < target.size(); i++) {
                    Map<String, Object> targetMap = target.get(i);
                    String targetTaskId = (String) targetMap.get("task_id");
                    Map<String, Object> exportMap = (Map<String, Object>) modelExport.get(targetTaskId);
                    List<Map<String, Object>> modelTargetList = (List<Map<String, Object>>) exportMap.get("models");
                    List<Map<String, Object>> outputList = (List<Map<String, Object>>) param_output.get(targetTaskId);

                    for (int j = 0; j < modelTargetList.size(); j++) {
                        Map<String, Object> targetModel = modelTargetList.get(i);
                        modelMetaVo.setId(Integer.valueOf((String) targetModel.get("model_id")));
                        modelMetaVo.setIdentifier((String) targetModel.get("model_identifier"));
                        modelMetaVo.setName((String) targetModel.get("model_name"));
                        modelMetaVo.setVersion((String) targetModel.get("model_version"));

//                        List<VersionVo> versionVos = new ArrayList<>();
//                        for (Map<String, Object> outputFile : outputList) {
//                            String path = (String) outputFile.get("path");
//                            List<Map<String, Object>> files = FileUtil.getFiles(path);
//                            for (Map<String, Object> fileDetail : files) {
//                                VersionVo versionVo = new VersionVo();
//                                versionVo.setUrl((String) fileDetail.get("filePath"));
//                                versionVo.setFileName((String) fileDetail.get("fileName"));
//                                long size = (long) fileDetail.get("size");
//                                versionVo.setFileSize(FileUtil.formatFileSize(size));
//                                versionVos.add(versionVo);
//                            }
//                        }
//                        modelMetaVo.setModelVersionVos(versionVos);

                        modelDependency.setRepoId(Integer.valueOf((String) targetModel.get("model_id")));
                        modelDependency.setIdentifier((String) targetModel.get("model_identifier"));
                        modelDependency.setVersion((String) targetModel.get("model_version"));
                        modelDependency.setModelName((String) targetModel.get("model_name"));
                        modelDependency.setMeta(JSON.toJSONString(modelMetaVo));
                        modelDependency1Dao.insert(modelDependency);
                    }
                }
            }
        }
    }

    /**
     * 被废弃的旧JSON
     *
     * @param experiment
     * @return
     * @throws Exception
     */
//    private void insertModelDependency(Map<String ,Object> dependendcy,Map<String ,Object> trainInfo, Integer experimentInsId, String experimentName, List<Map<String, Object>> params) throws Exception {
//        Iterator<Map.Entry<String, Object>> dependendcyIterator = dependendcy.entrySet().iterator();
//        while (dependendcyIterator.hasNext()) {
//            ModelDependency modelDependency = new ModelDependency();
//            Map.Entry<String, Object> entry = dependendcyIterator.next();
//            String key = entry.getKey();
//            Map<String, Object> modelDel = (Map<String, Object>) entry.getValue();
//            //处理project数据
//            Map<String, String> projectMap  = (Map<String, String>) modelDel.get("project");
//            ProjectDepency projectDepency = new ProjectDepency();
//            projectDepency.setBranch(projectMap.get("branch"));
//            String projectUrl = projectMap.get("url");
//            projectDepency.setUrl(projectUrl);
//            projectDepency.setName(projectUrl.substring(projectUrl.lastIndexOf('/') + 1, projectUrl.length() - 4));
//            //依赖项目
//            modelDependency.setProjectDependency(JsonUtils.objectToJson(projectDepency));
//            //处理source数据
//            Map<String, Object> sourceMap  = (Map<String, Object>) modelDel.get("source");
//            List<Map<String, Object>> modelsList = (List<Map<String, Object>>) sourceMap.get("models");
//            for(int i=0;i<modelsList.size();i++){
//                Map<String, Object> model = modelsList.get(i);
//                Models models = modelsService.queryById((Integer) model.get("model_id"));
//                if (models == null){
//                    throw new  Exception("源模型不存在");
//                }
//                model.put("model_name", models.getName());
//            }
//            //父模型
//            modelDependency.setParentModels(JsonUtils.objectToJson(modelsList));
//
//            List<Map<String, Object>> datasetsList = (List<Map<String, Object>>) sourceMap.get("datasets");
//            for(int i=0;i<datasetsList.size();i++){
//                Map<String, Object> datasets = datasetsList.get(i);
//                Dataset dataset = datasetService.queryById((Integer) datasets.get("dataset_id"));
//                if (dataset == null){
//                    throw new  Exception("源数据集不存在");
//                }
//                datasets.put("dataset_name", dataset.getName());
//            }
//            //训练数据集
//            modelDependency.setTrainDataset(JsonUtils.objectToJson(datasetsList));
//
//            TrainTaskDepency trainTaskDepency = new TrainTaskDepency();
//            trainTaskDepency.setTaskId(key);
//            trainTaskDepency.setInsId(experimentInsId);
//            trainTaskDepency.setName(experimentName);
//            //训练任务
//            modelDependency.setTrainTask(JsonUtils.objectToJson(trainTaskDepency));
//            modelDependency.setExpInsId(experimentInsId);
//            //处理test数据
//            List<Map<String, Object>> testDatasetsList = (List<Map<String, Object>>) modelDel.get("test");
//            List<Map<String, Object>> resultTestDatasets = new ArrayList<Map<String, Object>>();
//            for(int i=0;i<testDatasetsList.size();i++){
//                Map<String, Object> datasets = testDatasetsList.get(i);
//                List<Map<String, Object>> realDataSetList = (List<Map<String, Object>>)  datasets.get("datasets");
//                for(int j=0;j<realDataSetList.size();j++){
//                    Map<String, Object> realDataSet = realDataSetList.get(j);
//                    Dataset dataset = datasetService.queryById((Integer) realDataSet.get("dataset_id"));
//                    if (dataset == null){
//                        throw new Exception("源数据集不存在");
//                    }
//                    realDataSet.put("dataset_name", dataset.getName());
//                    resultTestDatasets.add(realDataSet);
//                }
//
//            }
//            //测试数据集
//            modelDependency.setTestDataset(JsonUtils.objectToJson(resultTestDatasets));
//
//            //检查是否存在target，如果存在说明在流水线用了节点导入，如果没有说明没有导入，等待手动push
//            List<Map<String, Object>> modelTargetList = (List<Map<String, Object>>) modelDel.get("target");
//            if (modelTargetList==null||modelTargetList.size()==0){
//                modelDependency.setState(1);
//                modelDependencyService.insert(modelDependency);
//            }else {
//                modelDependency.setState(2);
//                for(int i=0;i<modelTargetList.size();i++){
//                    Map<String, Object> model = modelTargetList.get(i);
//                    String version = null;
//                    //可能是参数，必须从实验参数读取
//                    if (params != null) {
//                        for (Map<String, Object> param : params) {
//                            if (param.containsKey("param_name") && StringUtils.equals("model_version",(String) param.get("param_name"))) {
//                                version = param.get("param_value").toString();
//                            }
//                        }
//                    }
//                    modelDependency.setVersion(StringUtils.isEmpty(version)?(String)model.get("model_version"):version);
//                    modelDependency.setCurrentModelId((Integer) model.get("model_id"));
//                    //因为可能有多成果模型，多次插入
//                    modelDependencyService.insert(modelDependency);
//                }
//            }
//        }
//    }
    @Override
    public Experiment addAndRunExperiment(Experiment experiment) throws Exception {
        // 第一步: 调用add方法插入实验记录到数据库
        Experiment newExperiment = this.insert(experiment);

        if (newExperiment == null) {
            throw new RuntimeException("Failed to add experiment.");
        }
        // 调用runExperiment方法运行实验
        try {
            newExperiment = this.runExperiment(newExperiment.getId());
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return newExperiment;
    }


    /**
     * 返回实验配置参数
     *
     * @param experiment 实例对象
     * @return 实验参数
     */
    @Override
    public ResponseEntity<Experiment> showExperimentConfig(Experiment experiment) {

        return null;
    }

    @Override
    public List<Experiment> queryByWorkflowId(Long id) {
        Experiment experiment = new Experiment();
        experiment.setWorkflowId(id);
        return experimentDao.queryByExperiment(experiment);
    }

    public void checkDeclaredName(Experiment insert) throws Exception {
        Experiment existingExperiment = experimentDao.findByName(insert.getName());

        if (existingExperiment != null) {
            // 检查找到的流水线是否与要插入的流水线相同
            if (insert.getId() != null && insert.getId().equals(existingExperiment.getId())) {
                // 这是相同的流水线，更新操作中没有重复名称问题
                return;
            }
            // 现在我们知道还有另一个具有相同名称的流水线
            Field[] fields = Experiment.class.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                if ("name".equals(field.getName()) && field.isAnnotationPresent(CheckDuplicate.class)) {
                    // 如果字段是“name”并且标记了CheckDuplicate注解
                    CheckDuplicate annotation = field.getAnnotation(CheckDuplicate.class);
                    throw new Exception("重复的实验名称: " + insert.getName() + ". " + annotation.message());
                }
            }
        }
    }


}
