package com.yunzhupaas.flowable.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.extension.mapping.wrapper.MappingQuery;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.flowable.entity.CandidatesEntity;
import com.yunzhupaas.flowable.entity.OperatorEntity;
import com.yunzhupaas.flowable.entity.TemplateNodeEntity;
import com.yunzhupaas.flowable.mapper.CandidatesMapper;
import com.yunzhupaas.flowable.model.task.FlowModel;
import com.yunzhupaas.flowable.model.util.FlowNature;
import com.yunzhupaas.flowable.service.CandidatesService;
import com.yunzhupaas.flowable.service.OperatorService;
import com.yunzhupaas.util.RandomUtil;
import com.yunzhupaas.util.StringUtil;
import com.yunzhupaas.util.UserProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/4/18 16:03
 */
@Service
public class CandidatesServiceImpl extends SuperServiceImpl<CandidatesMapper, CandidatesEntity>
        implements CandidatesService {
    @Autowired
    private OperatorService operatorService;

    @Override
    public List<CandidatesEntity> getList(String taskId, String nodeCode) {
        QueryWrapper<CandidatesEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtil.isNotEmpty(taskId)) {
            queryWrapper.lambda().eq(CandidatesEntity::getTaskId, taskId);
        }
        if (StringUtil.isNotEmpty(nodeCode)) {
            queryWrapper.lambda().eq(CandidatesEntity::getNodeCode, nodeCode);
        }
        return this.list(queryWrapper);
    }

    public List<CandidatesEntity> getListByCode(String taskId, String nodeCode) {
        QueryWrapper<CandidatesEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CandidatesEntity::getTaskId, taskId).eq(CandidatesEntity::getNodeCode, nodeCode);
        return this.list(queryWrapper);
    }

    @Override
    public void create(FlowModel fo, String taskId, List<TemplateNodeEntity> nodeEntityList, OperatorEntity operator) {
        UserInfo userInfo = UserProvider.getUser();
        // 候选人
        Map<String, List<String>> candidateList = fo.getCandidateList();
        for (String key : candidateList.keySet()) {
            TemplateNodeEntity nodeEntity = nodeEntityList.stream().filter(e -> e.getNodeCode().equals(key)).findFirst()
                    .orElse(null);
            if (null == nodeEntity) {
                continue;
            }
            // 删除原先的节点的候选人
            // this.delete(taskId, nodeEntity.getNodeCode());

            List<String> list = candidateList.get(key);
            this.create(taskId, nodeEntity, operator, userInfo, list, FlowNature.Candidates);
        }
        // 异常人
        Map<String, List<String>> errorRuleUserList = fo.getErrorRuleUserList();
        for (String key : errorRuleUserList.keySet()) {
            TemplateNodeEntity nodeEntity = nodeEntityList.stream().filter(e -> e.getNodeCode().equals(key)).findFirst()
                    .orElse(null);
            if (null == nodeEntity) {
                continue;
            }
            List<String> list = errorRuleUserList.get(key);
            this.create(taskId, nodeEntity, operator, userInfo, list, FlowNature.CandidatesError);
        }
    }

    public void create(String taskId, TemplateNodeEntity nodeEntity, OperatorEntity operator, UserInfo userInfo,
            List<String> list, Integer type) {
        CandidatesEntity entity = new CandidatesEntity();
        entity.setId(RandomUtil.uuId());
        entity.setTaskId(taskId);
        entity.setNodeCode(nodeEntity.getNodeCode());

        String nodeId = "";
        if (operator != null) {
            entity.setOperatorId(operator.getId());
            nodeId = operator.getNodeId();
        } else {
            entity.setOperatorId(FlowNature.ParentId);
        }
        List<CandidatesEntity> entityList = this.getListByCode(taskId, nodeEntity.getNodeCode());
        if (CollectionUtil.isNotEmpty(entityList)) {
            QueryWrapper<OperatorEntity> operatorWrapper = new QueryWrapper<>();
            operatorWrapper.lambda().eq(OperatorEntity::getTaskId, taskId).eq(OperatorEntity::getNodeId, nodeId);
            List<OperatorEntity> opList = operatorService.list(operatorWrapper);
            if (CollectionUtil.isNotEmpty(opList)) {
                List<String> opIds = opList.stream().map(OperatorEntity::getId).collect(Collectors.toList());
                List<CandidatesEntity> deleteList = entityList.stream()
                        .filter(e -> !opIds.contains(e.getOperatorId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(deleteList)) {
                    this.removeByIds(deleteList);
                }
            }
        }

        entity.setAccount(userInfo.getUserAccount());
        entity.setHandleId(userInfo.getUserId());
        entity.setType(type);

        entity.setCandidates(String.join(",", list));
        this.save(entity);
    }

    public void delete(String taskId, String nodeCode) {
        QueryWrapper<CandidatesEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CandidatesEntity::getTaskId, taskId)
                .eq(CandidatesEntity::getNodeCode, nodeCode);
        List<CandidatesEntity> list = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            this.removeByIds(list);
        }
    }

    @Override
    public void deleteByCodes(String taskId, List<String> nodeIds) {
        QueryWrapper<CandidatesEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CandidatesEntity::getTaskId, taskId);
        if (CollectionUtil.isNotEmpty(nodeIds)) {
            queryWrapper.lambda().in(CandidatesEntity::getNodeCode, nodeIds);
        }
        List<CandidatesEntity> list = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            this.removeByIds(list);
        }
    }

    @Override
    public void delete(String taskId, List<String> nodeIds, List<String> userId) {
        QueryWrapper<CandidatesEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CandidatesEntity::getTaskId, taskId).in(CandidatesEntity::getHandleId, userId);
        if (CollectionUtil.isNotEmpty(nodeIds)) {
            queryWrapper.lambda().in(CandidatesEntity::getNodeCode, nodeIds);
        }
        List<CandidatesEntity> list = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            this.removeByIds(list);
        }
    }

    @Override
    public List<String> getBranch(String taskId, String nodeCode) {
        List<String> resList = new ArrayList<>();
        QueryWrapper<CandidatesEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CandidatesEntity::getTaskId, taskId).eq(CandidatesEntity::getNodeCode, nodeCode)
                .eq(CandidatesEntity::getType, FlowNature.Branch);
        List<CandidatesEntity> list = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            for (CandidatesEntity entity : list) {
                if (StringUtil.isNotEmpty(entity.getCandidates())) {
                    List<String> branch = Arrays.stream(entity.getCandidates().split(",")).collect(Collectors.toList());
                    resList.addAll(branch);
                }
            }
        }
        return resList;
    }

    @Override
    public void createBranch(List<String> branchList, OperatorEntity operator) {
        if (CollectionUtil.isNotEmpty(branchList)) {
            this.deleteBranch(operator.getTaskId(), operator.getNodeCode());
            CandidatesEntity entity = new CandidatesEntity();
            entity.setId(RandomUtil.uuId());
            entity.setTaskId(operator.getTaskId());
            entity.setNodeCode(operator.getNodeCode());
            entity.setOperatorId(operator.getId());
            entity.setType(FlowNature.Branch);
            entity.setCandidates(String.join(",", branchList));
            this.save(entity);
        }
    }

    @Override
    public void deleteBranch(String taskId, String nodeCode) {
        QueryWrapper<CandidatesEntity> wrapper = new MappingQuery<>();
        wrapper.lambda().eq(CandidatesEntity::getTaskId, taskId).eq(CandidatesEntity::getNodeCode, nodeCode)
                .eq(CandidatesEntity::getType, FlowNature.Branch);
        this.remove(wrapper);
    }
}
