package cd.casic.ci.process.process.service.pipeline.impl;


import cd.casic.ci.process.dto.req.pipeline.*;
import cd.casic.ci.process.dto.req.template.TemplateCreateByDataReq;
import cd.casic.ci.process.dto.req.template.TemplateStageCreateByDataReq;
import cd.casic.ci.process.dto.req.template.TemplateTaskCreateByDataReq;
import cd.casic.ci.process.dto.resp.context.TreeRunContextResp;
import cd.casic.ci.process.dto.resp.pipeline.PipelineFindResp;
import cd.casic.ci.process.dto.resp.pipeline.PipelineUseCountResp;
import cd.casic.ci.process.dto.resp.stage.StageResp;
import cd.casic.ci.process.dto.resp.template.TemplateFindResp;
import cd.casic.ci.process.dto.resp.template.TemplateStageResp;
import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.engine.runContext.PipelineRunContext;
import cd.casic.ci.process.process.converter.PipelineConverter;
import cd.casic.ci.process.process.converter.TemplateConverter;
import cd.casic.ci.process.process.dao.pipeline.PipStageDao;
import cd.casic.ci.process.process.dao.pipeline.PipTaskDao;
import cd.casic.ci.process.process.dao.pipeline.PipelineDao;
import cd.casic.ci.process.process.dao.pipeline.TargetVersionDao;
import cd.casic.ci.process.process.dataObject.base.BaseIdReq;
import cd.casic.ci.process.process.dataObject.pipeline.PipPipeline;
import cd.casic.ci.process.process.dataObject.stage.PipStage;
import cd.casic.ci.process.process.dataObject.target.TargetVersion;
import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.dataObject.volumnInfo.VulInfo;
import cd.casic.ci.process.process.service.pipeline.PipelineService;
import cd.casic.ci.process.process.service.stage.impl.StageServiceImpl;
import cd.casic.ci.process.process.service.task.impl.TaskServiceImpl;
import cd.casic.ci.process.process.service.template.impl.TemplateManagerServiceImpl;
import cd.casic.ci.process.util.WebFrameworkUtils;
import cd.casic.ci.process.util.snowflake.SnowflakeIdentifierGenerator;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.framework.commons.pojo.PageResult;
import cd.casic.framework.security.dal.user.AdminUserDO;
import cd.casic.framework.tenant.core.service.AdminUserServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author HopeLi
 * @version v1.0
 * @ClassName PipelineServiceImpl
 * @Date: 2025/5/13 10:31
 * @Description:
 */
@Service
@Slf4j
public class PipelineServiceImpl extends ServiceImpl<PipelineDao, PipPipeline> implements PipelineService {
    @Resource
    private StageServiceImpl stageService;

    @Resource
    private TaskServiceImpl taskService;

    @Resource
    private PipelineDao pipelineDao;

    @Resource
    private PipStageDao pipStageDao;

    @Resource
    private PipTaskDao pipTaskDao;

    @Resource
    private AdminUserServiceImpl adminUserService;
    @Resource
    private RunContextManager contextManager;
    
    @Resource
    private TemplateManagerServiceImpl templateService;
    @Resource
    private PipelineConverter pipelineConverter;
    @Resource
    private TemplateConverter templateConverter;

    @Resource
    private TargetVersionDao targetVersionDao;

    @Resource
    private SnowflakeIdentifierGenerator idWork;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createPipeline(PipelineCreateReq pipelineReq) {
        List<PipStage> pipStageList = new ArrayList<>(0);
        List<PipTask> pipTaskList = new ArrayList<>(0);

        PipPipeline pipeline = pipelineConverter.reqToDO(pipelineReq);
        Long tenantId = WebFrameworkUtils.getLoginUser().getTenantId();
        pipeline.setTenantId(tenantId);
        // 随机颜色
        int randomNumber = (int)(Math.random() * 5) + 1;
        pipeline.setColor(randomNumber);

        pipeline.setState(1);

        this.save(pipeline);
        //如果模板id为空，则设置默认模板，只新增初始节点
        if (StringUtils.isEmpty(pipelineReq.getTemplateId())) {
            //新增父级阶段
            PipStage pipStage = new PipStage();
            String stageId = idWork.nextUUID(null);
            pipStage.setId(stageId);
            pipStage.setStageName("初始阶段");
            pipStage.setStageSort(1);
            pipStage.setParentId("-1");
            pipStage.setPipelineId(pipeline.getId());
            pipStage.setCode(true);
            pipStageDao.insert(pipStage);

            //新增子级阶段
            PipStage childPipStage = new PipStage();
            String childPipStageId = idWork.nextUUID(null);
            childPipStage.setId(childPipStageId);
            childPipStage.setStageName("初始阶段");
            childPipStage.setStageSort(1);
            childPipStage.setParentId(pipStage.getId());
            childPipStage.setPipelineId(pipeline.getId());
            childPipStage.setCode(true);
            pipStageDao.insert(childPipStage);

            //新增节点信息
            PipTask pipTask = new PipTask();
            pipTask.setStageId(childPipStage.getId());
            pipTask.setTaskName("初始节点");
            pipTask.setPipelineId(pipeline.getId());
            pipTask.setTaskType(pipelineReq.getTargetType());
            pipTask.setTaskSort(1);
            pipTask.setTaskProperties(new HashMap<>());
            pipTaskDao.insert(pipTask);

        }else {
            //根据模板ID初始化
            TemplateFindResp template = templateService.findTemplateById(pipelineReq.getTemplateId());

            if (!ObjectUtils.isEmpty(template)){

                //新增阶段数据
                List<TemplateStageResp> stageList = template.getStageList();
                stageList.forEach(o->{
                    PipStage pipStage = templateConverter.respToStage(o);
                    pipStage.setId(idWork.nextUUID(null));
                    pipStage.setPipelineId(pipeline.getId());
                    if (o.isCode()){
                        pipStage.setCode(true);
                    }else {
                        pipStage.setCode(false);
                    }
                    pipStageList.add(pipStage);

                    List<TemplateStageResp> childStageList = o.getStageList();
                    if (!CollectionUtils.isEmpty(childStageList)){
                        //则代表大阶段下存在阶段子节点
                        childStageList.forEach(j->{
                            PipStage childStage = templateConverter.respToStage(j);

                            childStage.setId(idWork.nextUUID(null));
                            childStage.setPipelineId(pipeline.getId());
                            childStage.setParentId(pipStage.getId());
                            childStage.setCreateTime(LocalDateTime.now());
                            childStage.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                            if (j.isCode()){
                                childStage.setCode(true);
                            }else {
                                childStage.setCode(false);
                            }

                            pipStageList.add(childStage);

                            if (!CollectionUtils.isEmpty(j.getTaskValues())){
                                List<PipTask> taskList = new ArrayList<>(0);
                                j.getTaskValues().forEach(k->{
                                    PipTask pipTask = templateConverter.templateTaskToTask(k);
                                    pipTask.setId(idWork.nextUUID(null));
                                    pipTask.setStageId(childStage.getId());
                                    pipTask.setPipelineId(pipeline.getId());
                                    pipTask.setCreateTime(LocalDateTime.now());
                                    pipTask.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                                    taskList.add(pipTask);
                                });
                                pipTaskList.addAll(taskList);
                            }
                        });
                    }
                });
            }else {
                throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"模板不存在");
            }
            pipStageDao.insertBatch(pipStageList);
            pipTaskDao.insertBatch(pipTaskList);
        }

        return pipeline.getId();
    }

    @Override
    public List<PipelineFindResp> findPipelineList(PipelineQueryReq pipelineQueryReq) {
        QueryWrapper<PipPipeline> wrapper = new QueryWrapper<>();
        if (!ObjectUtils.isEmpty(pipelineQueryReq.getId())){
            wrapper.eq("id",pipelineQueryReq.getId());
        }
        if (!ObjectUtils.isEmpty(pipelineQueryReq.getIdList())){
            wrapper.in("id",pipelineQueryReq.getId());
        }
        if (!ObjectUtils.isEmpty(pipelineQueryReq.getName())){
            wrapper.like("name",pipelineQueryReq.getName());
        }
        if (!ObjectUtils.isEmpty(pipelineQueryReq.getCreator())){
            wrapper.eq("creator",pipelineQueryReq.getCreator());
        }
        if (!ObjectUtils.isEmpty(pipelineQueryReq.getCollect())){
            wrapper.eq("collect",pipelineQueryReq.getCollect());
        }
        if (!ObjectUtils.isEmpty(pipelineQueryReq.getGroupId())){
            wrapper.eq("group_id",pipelineQueryReq.getGroupId());
        }
//        Page<PipPipeline> page = new Page<>(pipelineQueryReq.getPageNo(), pipelineQueryReq.getPageSize());
//        Page<PipPipeline> pipPipelinePage = pipelineDao.selectPage(page, wrapper);

        List<PipPipeline> pipPipelines = pipelineDao.selectList(wrapper);
        if (ObjectUtils.isEmpty(pipPipelines)){
            return new ArrayList<>(0);
        }

        List<PipelineFindResp> respList = PipelineConverter.INSTANCE.toRespList(pipPipelines);

        //对流水线进行流水线信息赋值
        respList.forEach(this::setStageAndTask);
        //对用户姓名进行赋值
//        respList.forEach(this::setUserName);
        setUserName(respList);
        return respList;
    }

    private void setStageAndTask(PipelineFindResp o) {
        List<StageResp> allStagesTask = stageService.findAllStagesTask(o.getId());
        o.setStageList(allStagesTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePipeline(PipelineReq req) {
        if (StringUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id不能为空");
        }

        String pipelineId = req.getId();

        if (ObjectUtils.isEmpty(pipelineId)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"请求参数不能为空");
        }

        PipPipeline pipeline = pipelineDao.selectById(pipelineId);
        if (ObjectUtils.isEmpty(pipeline)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"流水线不存在");
        }
        pipelineDao.deleteById(pipelineId);

        //根据流水线id查询节点和配置信息
        PipStage pipStage = new PipStage();
        pipStage.setPipelineId(pipelineId);
        List<PipStage> pipStageList = stageService.getPipStageList(pipStage);
        if (!CollectionUtils.isEmpty(pipStageList)){
            List<String> list = pipStageList.stream().map(PipStage::getId).toList();
            pipStageDao.deleteByIds(list);
        }

        PipTask pipTask = new PipTask();
        pipTask.setPipelineId(pipelineId);
        List<PipTask> task = taskService.getTask(pipTask);
        if (!CollectionUtils.isEmpty(task)){
            List<String> list = task.stream().map(PipTask::getId).toList();
            pipTaskDao.deleteByIds(list);
        }
    }

    @Override
    public void updatePipeline(PipelineUpdateReq pipeline) {
        PipPipeline pipPipeline = pipelineConverter.reqToDO(pipeline);
        pipPipeline.setUpdateTime(LocalDateTime.now());
        pipPipeline.setUpdater(String.valueOf(WebFrameworkUtils.getLoginUserId()));
        pipelineDao.updateById(pipPipeline);
    }

    @Override
    public PageResult<PipelineFindResp> findPipelinePage(PipelineQueryReq query) {

        LambdaQueryWrapper<PipPipeline> wrapper = new LambdaQueryWrapper<>();
        if (!ObjectUtils.isEmpty(query.getId())){
            wrapper.eq(PipPipeline::getId,query.getId());
        }
        if (!ObjectUtils.isEmpty(query.getIdList())){
            wrapper.in(PipPipeline::getId,query.getId());
        }
        if (!ObjectUtils.isEmpty(query.getName())){
            wrapper.like(PipPipeline::getName,query.getName());
        }
        if (!ObjectUtils.isEmpty(query.getCreator())){
            wrapper.eq(PipPipeline::getCreator,query.getCreator());
        }
        if (!ObjectUtils.isEmpty(query.getCollect())){
            wrapper.eq(PipPipeline::getCollect,query.getCollect());
        }
        if (!ObjectUtils.isEmpty(query.getGroupId())){
            wrapper.eq(PipPipeline::getGroupId,query.getGroupId());
        }
        wrapper.orderByDesc(PipPipeline::getCreateTime);
        Page<PipPipeline> pipPipelinePage = pipelineDao.selectPage(new Page<>(query.getPageNo(), query.getPageSize()), wrapper);

        if (ObjectUtils.isEmpty(pipPipelinePage)){
            return new PageResult<>();
        }

        List<PipelineFindResp> respList = PipelineConverter.INSTANCE.toRespList(pipPipelinePage.getRecords());

        //对流水线进行流水线信息赋值
//        respList.forEach(this::setStageAndTask);
//        respList.forEach(this::setUserName);
        setUserName(respList);
        PageResult<PipelineFindResp> pageResult = new PageResult<>(respList,pipPipelinePage.getTotal(),pipPipelinePage.getCurrent(),pipPipelinePage.getSize());
        return pageResult;
    }

    private void setUserName(List<PipelineFindResp> pipelineFindRespList) {
        Set<Long> userIdSet = new HashSet<>(pipelineFindRespList.size()*3);
        for (PipelineFindResp pipelineFindResp : pipelineFindRespList) {
            if (!StringUtils.isEmpty(pipelineFindResp.getCreator())){
                userIdSet.add(Long.valueOf(pipelineFindResp.getCreator()));
            }

            if (!StringUtils.isEmpty(pipelineFindResp.getUpdater())){
                userIdSet.add(Long.valueOf(pipelineFindResp.getUpdater()));
            }

            if (!StringUtils.isEmpty(pipelineFindResp.getExecuteUserId())){
                userIdSet.add(Long.valueOf(pipelineFindResp.getExecuteUserId()));
            }
        }
        Map<Long, AdminUserDO> userIdMap = adminUserService.getUserListByIds(userIdSet).stream().collect(Collectors.toMap(AdminUserDO::getId, Function.identity()));
        for (PipelineFindResp pipelineFindResp : pipelineFindRespList) {
            if (!StringUtils.isEmpty(pipelineFindResp.getCreator())){
                AdminUserDO user = userIdMap.get(Long.valueOf(pipelineFindResp.getCreator()));
                if (!ObjectUtils.isEmpty(user)){
                    pipelineFindResp.setCreatorName(user.getUsername());
                }
            }

            if (!StringUtils.isEmpty(pipelineFindResp.getUpdater())){
                AdminUserDO user = userIdMap.get(Long.valueOf(pipelineFindResp.getUpdater()));
                if (!ObjectUtils.isEmpty(user)){
                    pipelineFindResp.setUpdaterName(user.getUsername());
                }
            }

            if (!StringUtils.isEmpty(pipelineFindResp.getExecuteUserId())){
                AdminUserDO user = userIdMap.get(Long.valueOf(pipelineFindResp.getExecuteUserId()));
                if (!ObjectUtils.isEmpty(user)){
                    pipelineFindResp.setExecuteUserName(user.getUsername());
                }
            }
        }
    }

    @Override
    public void pipelineClone(PipelineReq req) {
        if (StringUtils.isEmpty(req.getId()) || StringUtils.isEmpty(req.getName())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"参数不能为空");
        }
        String pipelineId = req.getId();
        String pipelineName = req.getName();
        PipPipeline pipeline = pipelineDao.selectById(pipelineId);
        if (ObjectUtils.isEmpty(pipeline)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"数据错误，请联系管理员");
        }

        //复制pipeline
        pipeline.setId(null);
        pipeline.setName(pipelineName);
        pipeline.setCreateTime(LocalDateTime.now());
        pipeline.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
        this.save(pipeline);

        //复制stage
        //复制阶段
        PipStage pipStage = new PipStage();
        pipStage.setPipelineId(pipelineId);
        pipStage.setParentId("-1");
        List<PipStage> pipStageParentList = stageService.getPipStageList(pipStage);

        if (!CollectionUtils.isEmpty(pipStageParentList)){
            pipStageParentList.forEach(o->{

                //根据阶段id查询下游并行节点
                PipStage childStage = new PipStage();
                childStage.setPipelineId(pipelineId);
                childStage.setParentId(o.getId());
                List<PipStage> pipStageChildList = stageService.getPipStageList(childStage);

                //对查询结束的stage进行复制
                o.setId(null);
                o.setPipelineId(pipeline.getId());
                o.setCreateTime(LocalDateTime.now());
                o.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                stageService.save(o);

                if (!CollectionUtils.isEmpty(pipStageChildList)){
                    pipStageChildList.forEach(j->{

                        //根据stageId查询串行节点
                        PipTask pipTask = new PipTask();
                        pipTask.setPipelineId(pipelineId);
                        pipTask.setStageId(j.getId());
                        List<PipTask> taskList = taskService.getTask(pipTask);

                        //对查询结束的并行节点进行复制
                        j.setId(null);
                        j.setParentId(o.getId());
                        j.setPipelineId(pipeline.getId());
                        j.setCreateTime(LocalDateTime.now());
                        j.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                        stageService.save(j);

                        if (!CollectionUtils.isEmpty(taskList)){
                            taskList.forEach(k->{
                                k.setId(null);
                                k.setStageId(j.getId());
                                k.setPipelineId(pipeline.getId());
                                k.setCreateTime(LocalDateTime.now());
                                k.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                            });
                            taskService.saveBatch(taskList);
                        }
                    });
                }

            });
        }

        //TODO   复制状态下资源处理不明确，暂时只做resourceId的继承保留
    }

    @Override
    public PipelineFindResp findPipelineById(PipelineQueryReq pipelineQueryReq) {
        if (StringUtils.isEmpty(pipelineQueryReq.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id参数不能为空");
        }
        PipPipeline pipeline = pipelineDao.selectById(pipelineQueryReq.getId());
        if (ObjectUtils.isEmpty(pipeline)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"数据错误，请联系管理员");
        }
        PipelineFindResp resp = PipelineConverter.INSTANCE.toResp(pipeline);
        setStageAndTask(resp);
        setTargetId(resp);

        return resp;
    }

    private void setTargetId(PipelineFindResp resp) {
        if (!ObjectUtils.isEmpty(resp.getTargetVersionId())){
            TargetVersion targetVersion = targetVersionDao.selectById(resp.getTargetVersionId());

            if (!ObjectUtils.isEmpty(targetVersion)){
                resp.setTargetId(targetVersion.getTargetId());
            }
        }
    }

    @Override
    public TreeRunContextResp getPipelineRunState(String pipelineId) {
        BaseRunContext context = contextManager.getContext(pipelineId);
        if (context instanceof PipelineRunContext pipelineRunContext) {
            TreeRunContextResp pipeline = new TreeRunContextResp();
            pipeline.setId(pipelineRunContext.getContextDef().getId());
            pipeline.setState(pipelineRunContext.getState().get());
            pipeline.setStartTime(pipelineRunContext.getStartTime());
            pipeline.setEndTime(pipelineRunContext.getEndTime());
            pipeline.setUserId(pipelineRunContext.getUserId());
            pipeline.setNickName(pipelineRunContext.getNickName());
            Map<String,TreeRunContextResp> secondStageStateMap = new HashMap<>(pipelineRunContext.getChildContext().size());
            Map<String, BaseRunContext> childContext = pipelineRunContext.getChildContext();
            pipeline.setChild(secondStageStateMap);
            LinkedList<TreeRunContextResp> taskList = new LinkedList<>();
            pipeline.setTaskList(taskList);
            for (Map.Entry<String, BaseRunContext> secondEntry : childContext.entrySet()) {
                BaseRunContext value = secondEntry.getValue();
                String key = secondEntry.getKey();
                TreeRunContextResp secondStage = new TreeRunContextResp();
                secondStageStateMap.put(key,secondStage);
                secondStage.setId(key);
                secondStage.setState(value.getState().get());
                Map<String, BaseRunContext> taskIdContextMap = value.getChildContext();
                Map<String,TreeRunContextResp> taskStateMap = new HashMap<>(taskIdContextMap.size());
                secondStage.setChild(taskStateMap);
                for (Map.Entry<String, BaseRunContext> taskEntry : taskIdContextMap.entrySet()) {
                    BaseRunContext taskContext = taskEntry.getValue();
                    String taskId = taskEntry.getKey();
                    TreeRunContextResp taskState = new TreeRunContextResp();
                    taskState.setId(taskId);
                    taskState.setState(taskContext.getState().get());
                    taskState.setStartTime(taskContext.getStartTime());
                    taskState.setEndTime(taskContext.getEndTime());
                    taskStateMap.put(taskId,taskState);
                    taskList.add(taskState);
                    if (taskState.getEndTime()==null) {
                        taskState.setDuration(between(taskState.getStartTime(),LocalDateTime.now()));
                    } else {
                        taskState.setDuration(between(taskState.getStartTime(),taskState.getEndTime()));
                    }
                }
            }
            return pipeline;
        }

        return new TreeRunContextResp();
    }

    @Override
    public Long getGroupCount(String groupId) {
        if (StringUtils.isEmpty(groupId)) {
            return -1L;
        }
        LambdaQueryWrapper<PipPipeline> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PipPipeline::getGroupId,groupId);
        return pipelineDao.selectCount(wrapper);
    }

    @Override
    public void transformTemplateByPipeline(BaseIdReq req) {
        if (ObjectUtils.isEmpty(req.getId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"id不能为空");
        }

        PipelineQueryReq pipelineQueryReq = new PipelineQueryReq();
        pipelineQueryReq.setId(req.getId());
        PipelineFindResp pipeline = this.findPipelineById(pipelineQueryReq);

        if (ObjectUtils.isEmpty(pipeline)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"数据错误，请联系管理员");
        }

        TemplateCreateByDataReq templateCreateByDataReq = new TemplateCreateByDataReq();

        templateCreateByDataReq.setTemplateName(pipeline.getName());
        templateCreateByDataReq.setTemplateType(pipeline.getTargetType());
        templateCreateByDataReq.setRemark(pipeline.getRemark());

        if (!ObjectUtils.isEmpty(pipeline.getStageList())){
            List<TemplateStageCreateByDataReq> parentTemplateStageList = new ArrayList<>();
            pipeline.getStageList().forEach(o->{
                TemplateStageCreateByDataReq parentTemplateStage = new TemplateStageCreateByDataReq();
                parentTemplateStage.setStageName(o.getStageName());
                parentTemplateStage.setStageSort(o.getStageSort());
                if (o.isCode()){
                    parentTemplateStage.setCode(true);
                }

                if (!ObjectUtils.isEmpty(o.getStageList())){
                    List<TemplateStageCreateByDataReq> childTemplateStageList = new ArrayList<>();
                    o.getStageList().forEach(j->{
                        TemplateStageCreateByDataReq childTemplateStage = new TemplateStageCreateByDataReq();
                        childTemplateStage.setStageName(j.getStageName());
                        childTemplateStage.setStageSort(j.getStageSort());
                        if (j.isCode()){
                            childTemplateStage.setCode(true);
                        }

                        if (!ObjectUtils.isEmpty(j.getTaskValues())){
                            List<TemplateTaskCreateByDataReq> templateTaskList = new ArrayList<>();
                            j.getTaskValues().forEach(k->{
                                TemplateTaskCreateByDataReq templateTaskCreateByDataReq = new TemplateTaskCreateByDataReq();
                                templateTaskCreateByDataReq.setTaskName(k.getTaskName());
                                templateTaskCreateByDataReq.setTaskType(k.getTaskType());
                                templateTaskCreateByDataReq.setTaskSort(k.getTaskSort());
                                templateTaskCreateByDataReq.setTaskProperties(k.getTaskProperties());
                                templateTaskList.add(templateTaskCreateByDataReq);
                            });
                            childTemplateStage.setTaskCreateByDataReqList(templateTaskList);
                        }

                        childTemplateStageList.add(childTemplateStage);
                    });

                    parentTemplateStage.setStageCreateByDataReqList(childTemplateStageList);
                }

                parentTemplateStageList.add(parentTemplateStage);
            });

            templateCreateByDataReq.setStageCreateByDataReqList(parentTemplateStageList);
        }
        templateService.createTemplateByData(templateCreateByDataReq);
    }

    @Override
    public Boolean targetVersionInUse(List<String> targetVersionId) {
        if (CollectionUtils.isEmpty(targetVersionId)) {
            return false;
        }
        LambdaQueryWrapper<PipPipeline> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(PipPipeline::getTargetVersionId,targetVersionId);
        return pipelineDao.exists(wrapper);
    }

    @Override
    public String aiCreatePipeline(AiPipelineCreateReq req) {
        List<PipStage> pipStageList = new ArrayList<>(0);
        List<PipTask> pipTaskList = new ArrayList<>(0);

        PipPipeline pipeline = pipelineConverter.aiReqToDO(req);

        // 随机颜色
        int randomNumber = (int)(Math.random() * 5) + 1;
        pipeline.setColor(randomNumber);

        pipeline.setState(1);

        this.save(pipeline);

        TemplateFindResp template = new TemplateFindResp();
        if (!ObjectUtils.isEmpty(req.getTemplateId())){
            //则根据模板进行新增
            template = templateService.findTemplateById(req.getTemplateId());
        }else {
            //则根据ai生成的模板进行新增
            template = req.getTemplateFindResp();
        }

        if (!ObjectUtils.isEmpty(template)){

            //新增阶段数据
            List<TemplateStageResp> stageList = template.getStageList();
            stageList.forEach(o->{
                PipStage pipStage = templateConverter.respToStage(o);
                pipStage.setId(idWork.nextUUID(null));
                pipStage.setPipelineId(pipeline.getId());
                if (o.isCode()){
                    pipStage.setCode(true);
                }else {
                    pipStage.setCode(false);
                }
                pipStageList.add(pipStage);

                List<TemplateStageResp> childStageList = o.getStageList();
                if (!CollectionUtils.isEmpty(childStageList)){
                    //则代表大阶段下存在阶段子节点
                    childStageList.forEach(j->{
                        PipStage childStage = templateConverter.respToStage(j);

                        childStage.setId(idWork.nextUUID(null));
                        childStage.setPipelineId(pipeline.getId());
                        childStage.setParentId(pipStage.getId());
                        childStage.setCreateTime(LocalDateTime.now());
                        childStage.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                        if (j.isCode()){
                            childStage.setCode(true);
                        }else {
                            childStage.setCode(false);
                        }

                        pipStageList.add(childStage);

                        if (!CollectionUtils.isEmpty(j.getTaskValues())){
                            List<PipTask> taskList = new ArrayList<>(0);
                            j.getTaskValues().forEach(k->{
                                PipTask pipTask = templateConverter.templateTaskToTask(k);
                                pipTask.setId(idWork.nextUUID(null));
                                pipTask.setStageId(childStage.getId());
                                pipTask.setPipelineId(pipeline.getId());
                                pipTask.setCreateTime(LocalDateTime.now());
                                pipTask.setCreator(String.valueOf(WebFrameworkUtils.getLoginUserId()));
                                taskList.add(pipTask);
                            });
                            pipTaskList.addAll(taskList);
                        }
                    });
                }
            });
            if (!CollectionUtils.isEmpty(pipStageList)){
                pipStageDao.insertBatch(pipStageList);
            }
            if (!CollectionUtils.isEmpty(pipTaskList)){
                pipTaskDao.insertBatch(pipTaskList);
            }
        }
        return pipeline.getId();
    }

    private String between(LocalDateTime startTime,LocalDateTime endTime){
        if (startTime==null||endTime==null) {
            return "";
        }
        Duration between = Duration.between(startTime, endTime);
        long days = between.toDays();
        long hours = between.toHours()%24;
        long minutes = between.toMinutes() % 60;
        long seconds = between.toSeconds() % 60;
        StringBuilder stringBuilder = new StringBuilder();
        if (days>0) {
            stringBuilder.append(days).append("天");
        }
        if (hours>0) {
            stringBuilder.append(hours).append("小时");
        }
        if (minutes>0) {
            stringBuilder.append(minutes).append("分");
        }
        stringBuilder.append(seconds).append("秒");
        return stringBuilder.toString();
    }

    @Override
    public PipelineUseCountResp countPipelineByUserId(Long userId) {
        Integer count = pipelineDao.selectCount(new QueryWrapper<PipPipeline>().lambda().eq(Objects.nonNull(userId), PipPipeline::getCreator, userId)).intValue();
        Integer collect = pipelineDao.selectCount(new LambdaQueryWrapper<PipPipeline>().eq(Objects.nonNull(userId), PipPipeline::getCreator, userId)
                .eq(PipPipeline::getCollect, 1)).intValue();
        return PipelineUseCountResp.builder().work(count).involved(count).collect(collect).build();
    }
}
