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

import cd.casic.ci.process.dto.req.stage.StageUpdateReq;
import cd.casic.ci.process.dto.req.template.TemplateStageCreateReq;
import cd.casic.ci.process.dto.req.template.TemplateStageUpdateReq;
import cd.casic.ci.process.dto.req.template.TemplateTaskCreateReq;
import cd.casic.ci.process.dto.resp.template.TemplateStageResp;

import cd.casic.ci.process.process.converter.TemplateStageConverter;
import cd.casic.ci.process.process.dao.template.TemplateStageDao;
import cd.casic.ci.process.process.dataObject.stage.PipStage;
import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.dataObject.template.TemplateStage;
import cd.casic.ci.process.process.dataObject.template.TemplateTask;
import cd.casic.ci.process.process.service.template.TemplateStageService;
import cd.casic.ci.process.process.service.template.TemplateTaskService;
import cd.casic.ci.process.util.WebFrameworkUtils;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class TemplateStageServiceImpl extends ServiceImpl<TemplateStageDao, TemplateStage> implements TemplateStageService  {
    @Resource
    private TemplateStageDao stageDao;
    @Resource
    private TemplateTaskService templateTaskService;
    @Resource
    private TemplateStageConverter stageConverter;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createStagesOrTask(TemplateStageCreateReq stageReq) {
        String firstStageId = stageReq.getStageId();
        Integer stageSort = stageReq.getStageSort();
        TemplateTaskCreateReq task = stageReq.getTask();
        String taskName = task.getTaskName();
        String secondStageId = task.getStageId();
        Map<String,Object> taskProperties = task.getTaskProperties();
        String taskType = task.getTaskType();
        Integer taskSort = task.getTaskSort();
        String templateId = task.getTemplateId();
        Long loginUserId = WebFrameworkUtils.getLoginUserId();
        TemplateStage firstStage = null;
        // 判断是否需要新建阶段,如果没有传第一级tageId而传了sort就是需要创建阶段
        if (StringUtils.isEmpty(firstStageId)) {
            // 新建stage
            firstStage = new TemplateStage();
            firstStage.setStageName("阶段-"+stageSort);
            if (stageSort == null) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"参数有误");
            }
            firstStage.setStageSort(stageSort);
            firstStage.setCreateTime(LocalDateTime.now());
            firstStage.setParentId("-1");
            firstStage.setTemplateId(templateId);

            firstStage.setCreator(String.valueOf(loginUserId));
            firstStage.setUpdater(String.valueOf(loginUserId));
            firstStage.setUpdateTime(LocalDateTime.now());
            TemplateStage stageQuery = new TemplateStage();
            stageQuery.setTemplateId(templateId);
            stageQuery.setParentId("-1");
            List<TemplateStage> otherStageList = getTemplateStageList(stageQuery);
            if (!CollectionUtils.isEmpty(otherStageList)) {
                for (TemplateStage stage : otherStageList) {
                    if (stageSort<=stage.getStageSort()) {
                        stage.setStageSort(stage.getStageSort()+1);
                    }
                }
                updateBatchById(otherStageList);
            }
            save(firstStage);
        } else {
            TemplateStage stageQuery = new TemplateStage();
            stageQuery.setId(firstStageId);
            stageQuery.setParentId("-1");
            List<TemplateStage> pipStageList = getTemplateStageList(stageQuery);
            if (!CollectionUtils.isEmpty(pipStageList)) {
                firstStage = pipStageList.get(0);
            } else {
                throw  new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"阶段不存在");
            }
        }
        if (firstStage == null) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"创建节点失败");
        }
        TemplateStage secondStage = null;
        if (secondStageId==null||taskSort==null) {
            // 添加并行节点
            secondStage = new TemplateStage();
            TemplateStage stageQuery = new TemplateStage();
            stageQuery.setParentId(firstStage.getId());
            stageQuery.setTemplateId(templateId);
            List<TemplateStage> pipStageList = getTemplateStageList(stageQuery);
            if (CollectionUtils.isEmpty(pipStageList)) {
                secondStage.setStageSort(1);
            } else {
                secondStage.setStageSort(pipStageList.size()+1);
            }
            secondStage.setCreateTime(LocalDateTime.now());
            secondStage.setUpdateTime(LocalDateTime.now());
            secondStage.setCreator(String.valueOf(loginUserId));
            secondStage.setParentId(firstStage.getId());
            secondStage.setTemplateId(templateId);
            secondStage.setUpdater(String.valueOf(loginUserId));
            save(secondStage);
            taskSort=1;
            secondStageId = secondStage.getId();
        } else {
            secondStage = getById(secondStageId);
        }
        if (secondStage == null) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"创建节点失败");
        }
        List<TemplateTask> taskValues = templateTaskService.getTaskByStageIdList(Arrays.asList(secondStage.getId()));
        if (!CollectionUtils.isEmpty(taskValues)) {
            for (TemplateTask taskValue : taskValues) {
                if (taskValue.getTaskSort()>=taskSort) {
                    taskValue.setTaskSort(taskValue.getTaskSort()+1);
                }
            }
            templateTaskService.updateBatchById(taskValues);
        }
        // 保存task
        TemplateTask pipTask = new TemplateTask();
        pipTask.setTaskType(taskType);
        pipTask.setTaskSort(taskSort);
        pipTask.setStageId(secondStageId);
        pipTask.setTaskName(taskName);
        pipTask.setCreateTime(LocalDateTime.now());
        pipTask.setTaskProperties(taskProperties);
        pipTask.setTemplateId(templateId);
        pipTask.setUpdateTime(LocalDateTime.now());
        pipTask.setCreator(String.valueOf(loginUserId));
        pipTask.setUpdater(String.valueOf(loginUserId));
        templateTaskService.save(pipTask);
        return pipTask.getId();
    }

    @Override
    public List<TemplateStageResp> findAllStagesTask(String pipelineId) {
        //获取流水线主节点
        List<TemplateStage> stageMainStage = findAllMainStage(pipelineId);
        if (stageMainStage.isEmpty()){
            return Collections.emptyList();
        }
        List<TemplateStageResp> list = new ArrayList<>();
        for (TemplateStage stage : stageMainStage) {
            String stagesId = stage.getId();
            //获取从节点
            List<TemplateStage> allSecondStage = findSecondStageAndTask(stagesId);
            List<TemplateStageResp> stageRespList = stageConverter.converter(allSecondStage);
            TemplateStageResp stageResp = stageConverter.converter(stage);
            stageResp.setStageList(stageRespList);
            list.add(stageResp);
        }
        list.sort(Comparator.comparing(TemplateStageResp::getStageSort));
        return list;
    }

    @Override
    public List<TemplateStage> findAllFirstStagesAndChild(String pipelineId) {
        //获取流水线主节点
        List<TemplateStage> stageMainStage = findAllMainStage(pipelineId);
        if (stageMainStage.isEmpty()){
            return Collections.emptyList();
        }
        for (TemplateStage stage : stageMainStage) {
            String stagesId = stage.getId();
            //获取从节点
            List<TemplateStage> allStageStage = findSecondStageAndTask(stagesId);
            stage.setStageList(allStageStage);
        }
        stageMainStage.sort(Comparator.comparing(TemplateStage::getStageSort));
        return stageMainStage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStagesAndTask(String taskId) {
        TemplateTask taskQuery = new TemplateTask();
        taskQuery.setId(taskId);
        List<TemplateTask> taskList = templateTaskService.getTask(taskQuery);
        if (CollectionUtils.isEmpty(taskList)) {
            return;
        }
        TemplateTask task = taskList.get(0);
        templateTaskService.removeById(taskId);
        // 查询上一级stage下有无其他task 没有则连着stage删除
        String stageId = task.getStageId();
        String pipelineId = task.getTemplateId();
        taskQuery = new TemplateTask();
        taskQuery.setStageId(stageId);
        List<TemplateTask> otherTask = templateTaskService.getTask(taskQuery);
        if (CollectionUtils.isEmpty(otherTask)) {
            // 删除当前task的父stage，然后判断父stage的父级有无其他子级如果没有就继续删除当前阶段
            TemplateStage stageQuery = new TemplateStage();
            stageQuery.setTemplateId(pipelineId);
            stageQuery.setId(stageId);
            List<TemplateStage> currStageList = getTemplateStageList(stageQuery);
            if (CollectionUtils.isEmpty(currStageList)) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"stage不存在");
            }
            TemplateStage currStage = currStageList.get(0);
            deleteStages(stageId);
            String parentId = currStage.getParentId();
            stageQuery = new TemplateStage();
            stageQuery.setParentId(parentId);
            // 查询同阶段其他二级stage，如果不存在其他stage则删除阶段stage并整理sort值
            List<TemplateStage> otherStageList = getTemplateStageList(stageQuery);
            if (CollectionUtils.isEmpty(otherStageList)) {
                //没有其他并行路径就需要删除当前阶段
                deleteStages(parentId);
            } else {
                for (TemplateStage stage : otherStageList) {
                    if (currStage.getStageSort()<stage.getStageSort()) {
                        stage.setStageSort(stage.getStageSort()-1);
                    }
                }
                updateBatchById(otherStageList);
            }
        } else {
            for (TemplateTask pipTask : otherTask) {
                if (task.getTaskSort()<pipTask.getTaskSort()) {
                    pipTask.setTaskSort(pipTask.getTaskSort()-1);
                }
            }
            templateTaskService.updateBatchById(otherTask);
        }

    }



    public List<TemplateStage> getTemplateStageList(TemplateStage pipStage){
        LambdaQueryWrapper<TemplateStage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(pipStage.getId()),TemplateStage::getId,pipStage.getId());
        wrapper.eq(StringUtils.isNotEmpty(pipStage.getTemplateId()),TemplateStage::getTemplateId,pipStage.getTemplateId());
        wrapper.eq(StringUtils.isNotEmpty(pipStage.getParentId()),TemplateStage::getParentId,pipStage.getParentId());
        return stageDao.selectList(wrapper);
    }


    public List<TemplateStage> findAllMainStage(String pipelineId) {
        LambdaQueryWrapper<TemplateStage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TemplateStage::getTemplateId,pipelineId);
        wrapper.eq(TemplateStage::getParentId,"-1");
        return stageDao.selectList(wrapper);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStagesTask(TemplateStageUpdateReq stage) {
        String id = stage.getId();
        String stageName = stage.getStageName();
        Integer currStageSort = stage.getStageSort();
        Long loginUserId = WebFrameworkUtils.getLoginUserId();
        TemplateStage updateStage = getById(id);
        if (updateStage==null) {
            return;
        }

        updateStage.setUpdater(String.valueOf(loginUserId));
        updateStage.setUpdateTime(LocalDateTime.now());
        if (currStageSort == null) {
            updateStage.setStageName(stageName);
            updateById(updateStage);
        } else{
            Integer oldStageSort = updateStage.getStageSort();
            if (oldStageSort.equals(currStageSort)) {
                return;
            }
            TemplateStage query = new TemplateStage();
            query.setTemplateId(updateStage.getTemplateId());
            query.setParentId("-1");
            List<TemplateStage> stageList = getTemplateStageList(query);
            if (oldStageSort<currStageSort) {
                // 往右移动
                for (TemplateStage pipStage : stageList) {
                    if (!pipStage.getId().equals(updateStage.getId())) {
                        if (pipStage.getStageSort()>oldStageSort&&pipStage.getStageSort()<=currStageSort) {
                            pipStage.setStageSort(pipStage.getStageSort()-1);
                        }
                    } else{
                        pipStage.setStageSort(currStageSort);
                    }
                }
            } else {
                // 往左移动
                for (TemplateStage pipStage : stageList) {
                    if (!pipStage.getId().equals(updateStage.getId())) {
                        if (pipStage.getStageSort()<oldStageSort&&pipStage.getStageSort()>=currStageSort) {
                            pipStage.setStageSort(pipStage.getStageSort()+1);
                        }
                    } else {
                        pipStage.setStageSort(currStageSort);
                    }
                }
            }
            updateBatchById(stageList);
        }

    }
    public void deleteStages(String stageId) {
        stageDao.deleteById(stageId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFirstStage(String stageId) {
        List<TemplateStage> secondStageAndTask = findSecondStageAndTask(stageId);
        for (TemplateStage stage : secondStageAndTask) {
            List<TemplateTask> taskValues = stage.getTaskValues();
            if (!CollectionUtils.isEmpty(taskValues)) {
                List<String> taskIdList = taskValues.stream().map(TemplateTask::getId).toList();
                templateTaskService.removeBatchByIds(taskIdList);
            }
        }
        List<String> secondStageIdList = secondStageAndTask.stream().map(TemplateStage::getId).toList();
        removeBatchByIds(secondStageIdList);
        TemplateStage byId = getById(stageId);
        List<TemplateStage> allMainStage = findAllMainStage(byId.getTemplateId());
        List<TemplateStage> updateList = new ArrayList<>(allMainStage.size());
        for (TemplateStage stage : allMainStage) {
            if (byId.getStageSort()<stage.getStageSort()) {
                stage.setStageSort(stage.getStageSort()-1);
                updateList.add(stage);
            }
        }
        //如果删除的为最后一个新增阶段，则无需更新前面阶段的sort值
        if (!CollectionUtils.isEmpty(updateList)){
            stageDao.updateBatch(updateList);
        }
        stageDao.deleteById(stageId);
    }


    public List<TemplateStage> findSecondStageAndTask(String stagesId){
        List<TemplateStage> otherStage = findSecondStage(stagesId);
        List<TemplateStage> list = new ArrayList<>();
        List<String> stageIdList = otherStage.stream().map(TemplateStage::getId).toList();
        if (stageIdList.isEmpty()) {
            throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"当前阶段下不存在节点");
        }
        Map<String, List<TemplateTask>> stageIdTaskMap = templateTaskService.getTaskByStageIdList(stageIdList).stream().collect(Collectors.groupingBy(TemplateTask::getStageId));
        for (TemplateStage stage : otherStage) {
            //获取阶段配置及任务
            String otherId = stage.getId();
            List<TemplateTask> allStageTask = stageIdTaskMap.get(otherId);
            allStageTask.sort(Comparator.comparing(TemplateTask::getTaskSort));
            stage.setTaskValues(allStageTask);
            list.add(stage);
        }
        return list;
    }
    // 获取主stage（阶段）下的子stage
    public List<TemplateStage> findSecondStage(String stageId){
        LambdaQueryWrapper<TemplateStage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TemplateStage::getParentId,stageId);
        return stageDao.selectList(wrapper);
    }
    @Override
    @Transactional
    public void copyStage(String stageId) {
        // 查询当前stage（阶段下所有）
        TemplateStage firstStage = getById(stageId);
        Long loginUserId = WebFrameworkUtils.getLoginUserId();
        List<TemplateStage> allMainStage = findAllMainStage(firstStage.getTemplateId());
        List<TemplateStage> updateStageList = new ArrayList<>(allMainStage.size());
        for (TemplateStage stage : allMainStage) {
            if (stage.getStageSort()>firstStage.getStageSort()) {
                stage.setStageSort(stage.getStageSort()+1);
                updateStageList.add(stage);
            }
        }
        // 保存复制后的阶段，除了id和sort其他都一样
        firstStage.setId(null);
        firstStage.setStageSort(firstStage.getStageSort()+1);
        save(firstStage);
        updateBatchById(updateStageList);
        // 查询阶段下所有分支
        List<TemplateStage> secondStageList = findSecondStage(stageId);
        if (!CollectionUtils.isEmpty(secondStageList)) {
            List<String> stageIdList = secondStageList.stream().map(TemplateStage::getId).toList();
            List<TemplateTask> taskList = templateTaskService.getTaskByStageIdList(stageIdList);
            Map<String, List<TemplateTask>> stageIdMap = taskList.stream().collect(Collectors.groupingBy(TemplateTask::getStageId));
            for (TemplateStage secondStage : secondStageList) {
                secondStage.setCreator(String.valueOf(loginUserId));
                secondStage.setCreateTime(LocalDateTime.now());
                secondStage.setUpdateTime(LocalDateTime.now());
                secondStage.setUpdater(String.valueOf(loginUserId));
                secondStage.setParentId(firstStage.getId());
                String secondStageId = secondStage.getId();
                List<TemplateTask> childTask = stageIdMap.get(secondStageId);
                secondStage.setId(null);
                save(secondStage);
                for (TemplateTask pipTask : childTask) {
                    pipTask.setStageId(secondStage.getId());
                    pipTask.setId(null);
                    pipTask.setCreator(String.valueOf(loginUserId));
                    pipTask.setCreateTime(LocalDateTime.now());
                    pipTask.setUpdateTime(LocalDateTime.now());
                    pipTask.setUpdater(String.valueOf(loginUserId));
                }
                templateTaskService.saveBatch(childTask);
            }
        }

    }
}
