package com.ruoyi.platform.service.impl;

import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.platform.domain.*;
import com.ruoyi.platform.mapper.ModelDependencyDao;
import com.ruoyi.platform.service.*;
import com.ruoyi.platform.utils.JacksonUtil;
import com.ruoyi.platform.vo.ModelDependcyTreeVo;
import com.ruoyi.platform.vo.ModelVersionDependcyVo;
import com.ruoyi.system.api.model.LoginUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (ModelDependency)表服务实现类
 *
 * @author Xidaray
 * @since 2024-05-29 13:51:23
 */
@Service("modelDependencyService")
public class ModelDependencyServiceImpl implements ModelDependencyService {
    @Resource
    private ModelDependencyDao modelDependencyDao;

    @Resource
    private ModelsService modelsService;
    @Resource
    private ModelsVersionService modelsVersionService;
    @Lazy
    @Resource
    private ExperimentService experimentService;
    @Lazy
    @Resource
    private ExperimentInsService experimentInsService;
    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ModelDependency queryById(Integer id) {
        return this.modelDependencyDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param modelDependency 筛选条件
     * @param pageRequest      分页对象
     * @return 查询结果
     */
    @Override
    public Page<ModelDependency> queryByPage(ModelDependency modelDependency, PageRequest pageRequest) {
        long total = this.modelDependencyDao.count(modelDependency);
        return new PageImpl<>(this.modelDependencyDao.queryAllByLimit(modelDependency, pageRequest), pageRequest, total);
    }

    /**
     * 根据对象查询
     *
     * @param modelDependency 筛选条件
     * @return 查询结果
     */
    @Override
    public List<ModelDependency> queryByModelDependency(ModelDependency modelDependency) throws IOException {
        List<ModelDependency> modelDependencyList = this.modelDependencyDao.queryByModelDependency(modelDependency);
        return modelDependencyList;
    }

    @Override
    public ModelDependcyTreeVo getModelDependencyTree(ModelDependency modelDependencyQuery) throws Exception {
        //查询当前模型
        modelDependencyQuery.setState(1);
        List<ModelDependency> modelDependencyList = this.queryByModelDependency(modelDependencyQuery);
        if (modelDependencyList==null || modelDependencyList.size()==0){
            throw new Exception("当前模型依赖关系不存在");
        }
        ModelDependency modelDependency = modelDependencyList.get(0);
        ModelDependcyTreeVo modelDependcyTreeVo = ModelDependencyConvertToTree(modelDependency);
        //递归父模型
        processParentModel(modelDependcyTreeVo);
        //递归子模型
        processChildrenModel(modelDependcyTreeVo);
        return modelDependcyTreeVo;
    }

    @Override
    public List<ModelDependency> queryByIns(Integer expInsId) {
        return modelDependencyDao.queryByIns(expInsId);
    }

    @Override
    public ModelDependency queryByInsAndTrainTaskId(Integer expInsId, String taskId) {
        return modelDependencyDao.queryByInsAndTrainTaskId(expInsId,taskId);
    }

    /**
     * 递归父模型
     * @param modelDependcyTreeVo
     */
    private void processParentModel(ModelDependcyTreeVo modelDependcyTreeVo) throws IOException {
        if (modelDependcyTreeVo.getParentModelsMap() != null) {
            List<Map<String, Object>> parentMaps = modelDependcyTreeVo.getParentModelsMap();
            List<ModelDependcyTreeVo> ps = new ArrayList<ModelDependcyTreeVo>();
            for (Map<String, Object> parent:parentMaps) {
                Integer model_id = (Integer) parent.get("model_id");
                String version = (String) parent.get("model_version");
                ModelDependency modelDependencyQuery = new ModelDependency();
                modelDependencyQuery.setVersion(version);
                modelDependencyQuery.setCurrentModelId(model_id);
                List<ModelDependency> modelDependencyList = this.queryByModelDependency(modelDependencyQuery);
                if (modelDependencyList!=null&&modelDependencyList.size()>=0){
                    for (ModelDependency modelDependency:modelDependencyList){
                        ModelDependcyTreeVo modelDependencyTreeVoIn = ModelDependencyConvertToTree(modelDependency);
                        processParentModel(modelDependencyTreeVoIn);
                        ps.add(modelDependencyTreeVoIn);
                    }
                }

            }
            modelDependcyTreeVo.setParentModels(ps);
        }
    }


    private void processChildrenModel(ModelDependcyTreeVo modelDependcyTreeVo) throws IOException {
        String version = modelDependcyTreeVo.getVersion();
        Integer modelId = modelDependcyTreeVo.getCurrentModelId();
        List<ModelDependcyTreeVo> cs = new ArrayList<ModelDependcyTreeVo>();
        //查儿子们

        List<ModelDependency> modelDependencyList = modelDependencyDao.queryChildrenByVersionId("\"model_id\":"+modelId, "\"model_version\":\""+version+"\"");
        if (modelDependencyList!=null&&modelDependencyList.size()>=0){
            for (ModelDependency modelDependency:modelDependencyList){
                ModelDependcyTreeVo modelDependencyTreeVoIn = ModelDependencyConvertToTree(modelDependency);
                processChildrenModel(modelDependencyTreeVoIn);
                cs.add(modelDependencyTreeVoIn);
            }
        }
        modelDependcyTreeVo.setChildrenModels(cs);
    }

    private ModelDependcyTreeVo ModelDependencyConvertToTree(ModelDependency modelDependency) throws IOException {
        ModelDependcyTreeVo modelDependcyTreeVo = new ModelDependcyTreeVo();
        modelDependcyTreeVo.setCurrentModelId(modelDependency.getCurrentModelId());
        modelDependcyTreeVo.setExpInsId(modelDependency.getExpInsId());
        modelDependcyTreeVo.setVersion(modelDependency.getVersion());
        modelDependcyTreeVo.setRefItem(modelDependency.getRefItem());
        modelDependcyTreeVo.setTrainTask(JacksonUtil.parseJSONStr2Map(modelDependency.getTrainTask()));
        modelDependcyTreeVo.setTrainDataset(JacksonUtil.parseJSONStr2MapList(modelDependency.getTrainDataset()));
        modelDependcyTreeVo.setTrainImage(modelDependency.getTrainImage());
        modelDependcyTreeVo.setTrainParams(JacksonUtil.parseJSONStr2TList(modelDependency.getTrainParams(),Object.class,null));
        modelDependcyTreeVo.setTestDataset(JacksonUtil.parseJSONStr2MapList(modelDependency.getTestDataset()));
        modelDependcyTreeVo.setProjectDependency(JacksonUtil.parseJSONStr2Map(modelDependency.getProjectDependency()));
        modelDependcyTreeVo.setParentModelsMap(JacksonUtil.parseJSONStr2MapList(modelDependency.getParentModels()));

        /**
         * 补充workFlow_id + 是否共有
         */
        Integer currentModelId = modelDependency.getCurrentModelId();
        Integer expInsId = modelDependency.getExpInsId();
        Models models = modelsService.queryById(currentModelId);
        ModelsVersion modelsVersionquery = new ModelsVersion();
        modelsVersionquery.setModelsId(currentModelId);
        modelsVersionquery.setVersion(modelDependency.getVersion());
        ModelsVersion modelsVersion = modelsVersionService.queryByModelsVersion(modelsVersionquery);
        ModelVersionDependcyVo modelVersionDependcyVo = new ModelVersionDependcyVo();
        modelVersionDependcyVo.setName(models.getName());
        modelVersionDependcyVo.setAvailableRange(models.getAvailableRange());
        modelVersionDependcyVo.setDescription(models.getDescription());
        modelVersionDependcyVo.setModelTag(models.getModelTag());
        modelVersionDependcyVo.setModelType(models.getModelType());
        modelVersionDependcyVo.setModelTagName(models.getModelTagName());
        modelVersionDependcyVo.setModelTypeName(models.getModelTypeName());
        modelVersionDependcyVo.setFileName(modelsVersion.getFileName());
        modelVersionDependcyVo.setFileSize(modelsVersion.getFileSize());
        modelVersionDependcyVo.setUrl(modelsVersion.getUrl());
        modelVersionDependcyVo.setCreateBy(modelsVersion.getCreateBy());
        modelVersionDependcyVo.setCreateTime(modelsVersion.getCreateTime());
        modelDependcyTreeVo.setModelVersionDependcyVo(modelVersionDependcyVo);
        ExperimentIns  experimentIns = experimentInsService.queryById(expInsId);
        if (experimentIns == null){
            return modelDependcyTreeVo;
        }
        Experiment experiment = experimentService.queryById(experimentIns.getExperimentId());
        if (experiment == null){
            return modelDependcyTreeVo;
        }
        modelDependcyTreeVo.setWorkflowId(experiment.getWorkflowId());
        return modelDependcyTreeVo;
    }

    /**
     * 新增数据
     *
     * @param modelDependency 实例对象
     * @return 实例对象
     */
    @Override
    public ModelDependency insert(ModelDependency modelDependency) {
        //插入预备，此时不需要判断版本重复
        LoginUser loginUser = SecurityUtils.getLoginUser();
        modelDependency.setCreateBy(loginUser.getUsername());
        modelDependency.setUpdateBy(loginUser.getUsername());
        modelDependency.setUpdateTime(new Date());
        modelDependency.setCreateTime(new Date());
        this.modelDependencyDao.insert(modelDependency);
        return modelDependency;
    }

    /**
     * 修改数据
     *
     * @param modelDependency 实例对象
     * @return 实例对象
     */
    @Override
    public ModelDependency update(ModelDependency modelDependency) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        modelDependency.setUpdateBy(loginUser.getUsername());
        modelDependency.setUpdateTime(new Date());
        this.modelDependencyDao.update(modelDependency);
        return this.queryById(modelDependency.getId());
    }

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

    @Override
    public String removeById(Integer id) throws Exception {
        ModelDependency modelDependency = this.modelDependencyDao.queryById(id);
        if (modelDependency == null){
            return "模型依赖信息不存在";
        }

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

        modelDependency.setState(0);
        return this.modelDependencyDao.update(modelDependency)>0?"删除成功":"删除失败";
    }

}
