package com.ruoyi.platform.service.impl;

import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.platform.annotations.CheckDuplicate;
import com.ruoyi.platform.domain.Dataset;
import com.ruoyi.platform.domain.Experiment;
import com.ruoyi.platform.domain.Workflow;
import com.ruoyi.platform.mapper.WorkflowDao;
import com.ruoyi.platform.service.ExperimentService;
import com.ruoyi.platform.service.WorkflowService;
import com.ruoyi.platform.utils.HttpUtils;
import com.ruoyi.platform.utils.JsonUtils;
import com.ruoyi.platform.utils.MinioUtil;
import com.ruoyi.system.api.model.LoginUser;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * DAG workflow(Workflow)表服务实现类
 *
 * @author makejava
 * @since 2023-10-18 14:17:10
 */
@Service("workflowService")
public class WorkflowServiceImpl implements WorkflowService {
    @Resource
    private WorkflowDao workflowDao;

    @Resource
    private ExperimentService experimentService;

    @Value("${argo.url}")
    private String argoUrl;

    @Value("${argo.workflowCopy}")
    private String argoWorkflowCopy;

    private final MinioUtil minioUtil;

    public WorkflowServiceImpl(MinioUtil minioUtil) {
        this.minioUtil = minioUtil;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Workflow queryById(Long id) {
        return this.workflowDao.queryById(id);
    }

    public WorkflowDao getWorkflowDao() {
        return workflowDao;
    }

    public void setWorkflowDao(WorkflowDao workflowDao) {
        this.workflowDao = workflowDao;
    }

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

    /**
     * 新增数据
     *
     * @param workflow 实例对象
     * @return 实例对象
     */
    @Override
    public Workflow insert(Workflow workflow) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        checkDeclaredName(workflow);
        workflow.setCreateBy(loginUser.getUsername());
        workflow.setUpdateBy(loginUser.getUsername());
        workflow.setUpdateTime(new Date());
        workflow.setCreateTime(new Date());
        workflow.setState(1);
        this.workflowDao.insert(workflow);
        return workflow;
    }

    /**
     * 修改数据
     *
     * @param workflow 实例对象
     * @return 实例对象
     */
    @Override
    public Workflow update(Workflow workflow) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        checkDeclaredName(workflow);
        workflow.setUpdateBy(loginUser.getUsername());
        workflow.setUpdateTime(new Date());
        this.workflowDao.update(workflow);
        return this.queryById(workflow.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.workflowDao.deleteById(id) > 0;
    }
    @Override
    public String removeById(Long id) throws Exception {
        //先根据id提取出对应的流水线
        Workflow workflow = workflowDao.queryById(id);
        if (workflow == null){
            throw new Exception("流水线不存在");
        }
        //判断权限，只有admin和创建者本身可以删除该流水线
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String username = loginUser.getUsername();
        String createdBy = workflow.getCreateBy();
        if (!(StringUtils.equals(username,"admin") || StringUtils.equals(username,createdBy))){
            throw new Exception("无权限删除该流水线");
        }

        //判断这个流水线是否有相关实验存在
        List<Experiment> experimentList = experimentService.queryByWorkflowId(id);
        if (experimentList!=null&&experimentList.size()>0){
            throw new Exception("该流水线存在实验，无法删除");
        }
        workflow.setState(0);
        return this.workflowDao.update(workflow)>0?"删除成功":"删除失败";
    }
    @Override
    public Page<Workflow> queryByName(String name) {
        return new PageImpl<>(this.workflowDao.queryByName(name));
    }



    @Override
    public Workflow duplicateWorkflow(Long id) {
        //先去查找数据库中存在的数据
        Workflow workflow = this.queryById(id);
        if (workflow!= null) {
            try {
                Workflow duplicateWorkflow = new Workflow();
                duplicateWorkflow.setName(workflow.getName()+"-copy");
                String oldDag = workflow.getDag();
                // 创建请求数据的Json(map)
                Map<String,Object> requestData = new HashMap<>();
                requestData.put("data", oldDag);
                // 发送POST请求到Argo工作流复制接口，并将请求数据转换为JSON
                String req = HttpUtils.sendPost(argoUrl + argoWorkflowCopy , JsonUtils.mapToJson(requestData));
                // 检查响应是否为空或无内容
                if (StringUtils.isEmpty(req)) {
                    throw new RuntimeException("工作流复制接口响应内容为空");
                }
                // 将响应的JSON字符串转换为Map对象
                Map<String, Object> runResMap = JsonUtils.jsonToMap(req);
                // 从响应Map中获取"data"的值,也就是日志的值
                String newDag = (String) runResMap.get("data");
                if (newDag == null){
                    throw new RuntimeException("响应内容为空。");
                }
                duplicateWorkflow.setDag(newDag);
                duplicateWorkflow.setDescription(workflow.getDescription());
                duplicateWorkflow.setGlobalParam(workflow.getGlobalParam());
                return this.insert(duplicateWorkflow);
            } catch (Exception e) {
                throw new RuntimeException("复制流水线失败: " + e.getMessage(), e);

            }
        }
        return null;



    }

    public void checkDeclaredName(Workflow insert) throws Exception {
        Workflow existingWorkflow = workflowDao.findByName(insert.getName());
        if (existingWorkflow != null) {
            // 检查找到的流水线是否与要插入的流水线相同
            if (insert.getId() != null && insert.getId().equals(existingWorkflow.getId())) {
                // 这是相同的流水线，更新操作中没有重复名称问题
                return;
            }
            Field[] fields = Workflow.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());
                }
            }
        }
    }




}
