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


import cd.casic.ci.process.dto.req.stage.StageCreateReq;
import cd.casic.ci.process.dto.req.stage.StageUpdateReq;
import cd.casic.ci.process.dto.req.task.TaskCreateReq;
import cd.casic.ci.process.dto.resp.context.SingletonRunContextResp;
import cd.casic.ci.process.dto.resp.stage.StageResp;
import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.process.converter.StageConverter;
import cd.casic.ci.process.process.dao.pipeline.PipStageDao;
import cd.casic.ci.process.process.dataObject.stage.PipStage;
import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.service.stage.StageService;
import cd.casic.ci.process.process.service.task.TaskService;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.ci.process.util.WebFrameworkUtils;
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 StageServiceImpl extends ServiceImpl<PipStageDao, PipStage> implements StageService {
    @Resource
    private TaskService taskService;
    @Resource
    private PipStageDao stageDao;
    @Resource
    private RunContextManager contextManager;
    @Resource
    private StageConverter stageConverter;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createStagesOrTask(StageCreateReq stageReq) {
        String firstStageId = stageReq.getStageId();
        Integer stageSort = stageReq.getStageSort();
        TaskCreateReq 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 pipelineId = task.getPipelineId();
        Long loginUserId = WebFrameworkUtils.getLoginUserId();
        PipStage firstStage = null;
        // 判断是否需要新建阶段,如果没有传第一级tageId而传了sort就是需要创建阶段
        if (StringUtils.isEmpty(firstStageId)) {
            // 新建stage
            firstStage = new PipStage();
            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.setPipelineId(pipelineId);

            firstStage.setCreator(String.valueOf(loginUserId));
            firstStage.setUpdater(String.valueOf(loginUserId));
            firstStage.setUpdateTime(LocalDateTime.now());
            PipStage stageQuery = new PipStage();
            stageQuery.setPipelineId(pipelineId);
            stageQuery.setParentId("-1");
            List<PipStage> otherStageList = getPipStageList(stageQuery);
            if (!CollectionUtils.isEmpty(otherStageList)) {
                for (PipStage stage : otherStageList) {
                    if (stageSort<=stage.getStageSort()) {
                        stage.setStageSort(stage.getStageSort()+1);
                    }
                }
                updateBatchById(otherStageList);
            }
            save(firstStage);
        } else {
            PipStage stageQuery = new PipStage();
            stageQuery.setId(firstStageId);
            stageQuery.setParentId("-1");
            List<PipStage> pipStageList = getPipStageList(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(),"创建节点失败");
        }
        PipStage secondStage = null;
        if (secondStageId==null||taskSort==null) {
            // 添加并行节点
            secondStage = new PipStage();
            PipStage stageQuery = new PipStage();
            stageQuery.setParentId(firstStage.getId());
            stageQuery.setPipelineId(pipelineId);
            List<PipStage> pipStageList = getPipStageList(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.setPipelineId(pipelineId);
            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<PipTask> taskValues = taskService.getTaskByStageIdList(Arrays.asList(secondStage.getId()));
        if (!CollectionUtils.isEmpty(taskValues)) {
            for (PipTask taskValue : taskValues) {
                if (taskValue.getTaskSort()>=taskSort) {
                    taskValue.setTaskSort(taskValue.getTaskSort()+1);
                }
            }
            taskService.updateBatchById(taskValues);
        }
        // 保存task
        PipTask pipTask = new PipTask();
        pipTask.setTaskType(taskType);
        pipTask.setTaskSort(taskSort);
        pipTask.setStageId(secondStageId);
        pipTask.setTaskName(taskName);
        pipTask.setCreateTime(LocalDateTime.now());
        pipTask.setTaskProperties(taskProperties);
        pipTask.setPipelineId(pipelineId);
        pipTask.setUpdateTime(LocalDateTime.now());
        pipTask.setCreator(String.valueOf(loginUserId));
        pipTask.setUpdater(String.valueOf(loginUserId));
        taskService.save(pipTask);
        return pipTask.getId();
    }

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

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

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

    }

    @Override
    public void deleteAllStagesOrTask(String pipelineId) {
        // TODO 删除流水线，不知道要不要
    }

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

    @Override
    public List<PipStage> findAllMainStage(String pipelineId) {
        LambdaQueryWrapper<PipStage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PipStage::getPipelineId,pipelineId);
        wrapper.eq(PipStage::getParentId,"-1");
        return stageDao.selectList(wrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateStagesTask(StageUpdateReq stage) {
        String id = stage.getId();
        String stageName = stage.getStageName();
        Integer currStageSort = stage.getStageSort();
        Long loginUserId = WebFrameworkUtils.getLoginUserId();
        PipStage 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;
            }
            PipStage query = new PipStage();
            query.setPipelineId(updateStage.getPipelineId());
            query.setParentId("-1");
            List<PipStage> stageList = getPipStageList(query);
            if (oldStageSort<currStageSort) {
                // 往右移动
                for (PipStage 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 (PipStage 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);
        }

    }

    @Override
    public List<String> validStagesMustField(String pipelineId) {
        return null;
    }



    @Override
    public void updateStages(PipStage stage) {
        stageDao.updateById(stage);
    }

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

    @Override
    @Transactional
    public void copyStage(String stageId) {
        // 查询当前stage（阶段下所有）
        PipStage firstStage = getById(stageId);
        Long loginUserId = WebFrameworkUtils.getLoginUserId();
        List<PipStage> allMainStage = findAllMainStage(firstStage.getPipelineId());
        List<PipStage> updateStageList = new ArrayList<>(allMainStage.size());
        for (PipStage 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<PipStage> secondStageList = findSecondStage(stageId);
        if (!CollectionUtils.isEmpty(secondStageList)) {
            List<String> stageIdList = secondStageList.stream().map(PipStage::getId).toList();
            List<PipTask> taskList = taskService.getTaskByStageIdList(stageIdList);
            Map<String, List<PipTask>> stageIdMap = taskList.stream().collect(Collectors.groupingBy(PipTask::getStageId));
            for (PipStage 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<PipTask> childTask = stageIdMap.get(secondStageId);
                secondStage.setId(null);
                save(secondStage);
                for (PipTask 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));
                }
                taskService.saveBatch(childTask);
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFirstStage(String stageId) {
        List<PipStage> secondStageAndTask = findSecondStageAndTask(stageId);
        for (PipStage stage : secondStageAndTask) {
            List<PipTask> taskValues = stage.getTaskValues();
            if (!CollectionUtils.isEmpty(taskValues)) {
                List<String> taskIdList = taskValues.stream().map(PipTask::getId).toList();
                taskService.removeBatchByIds(taskIdList);
            }
        }
        List<String> secondStageIdList = secondStageAndTask.stream().map(PipStage::getId).toList();
        removeBatchByIds(secondStageIdList);
        PipStage byId = getById(stageId);
        List<PipStage> allMainStage = findAllMainStage(byId.getPipelineId());
        List<PipStage> updateList = new ArrayList<>(allMainStage.size());
        for (PipStage 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);
    }

    @Override
    public Map<String, SingletonRunContextResp> getStageRunState(String stageId) {
        PipStage byId = getById(stageId);
        Map<String, SingletonRunContextResp> result = new HashMap<>();
        if (byId==null||"-1".equals(byId.getParentId())) {
            log.error("传入stageId非阶段id");
            return result;
        }
        List<PipStage> secondStage = findSecondStageAndTask(stageId);

        for (PipStage stage : secondStage) {
            String id = stage.getId();
            List<PipTask> taskValues = stage.getTaskValues();
            for (PipTask taskValue : taskValues) {
                BaseRunContext context = contextManager.getContext(taskValue.getId());
                if (context==null) {
                    break;
                }
                String taskId = taskValue.getId();
                int state = context.getState().get();
                SingletonRunContextResp runContextResp = new SingletonRunContextResp();
                runContextResp.setState(state);
                runContextResp.setId(taskId);
                result.put(taskId,runContextResp);
            }
        }
        return result;
    }

    public List<PipStage> findSecondStageAndTask(String stagesId){
        List<PipStage> otherStage = findSecondStage(stagesId);
        List<PipStage> list = new ArrayList<>();
        List<String> stageIdList = otherStage.stream().map(PipStage::getId).toList();
        if (stageIdList.isEmpty()) {
            throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"当前阶段下不存在节点");
        }
        Map<String, List<PipTask>> stageIdTaskMap = taskService.getTaskByStageIdList(stageIdList).stream().collect(Collectors.groupingBy(PipTask::getStageId));
        for (PipStage stage : otherStage) {
            //获取阶段配置及任务
            String otherId = stage.getId();
            List<PipTask> allStageTask = stageIdTaskMap.get(otherId);
            allStageTask.sort(Comparator.comparing(PipTask::getTaskSort));
            stage.setTaskValues(allStageTask);
            list.add(stage);
        }
        return list;
    }
    // 获取主stage（阶段）下的子stage
    @Override
    public List<PipStage> findSecondStage(String stageId){
        LambdaQueryWrapper<PipStage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PipStage::getParentId,stageId);
        return stageDao.selectList(wrapper);
    }
}
